1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Extended attribute handling for AFS. We use xattrs to get and set metadata 3 * instead of providing pioctl(). 4 * 5 * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved. 6 * Written by David Howells (dhowells@redhat.com) 7 */ 8 9 #include <linux/slab.h> 10 #include <linux/fs.h> 11 #include <linux/xattr.h> 12 #include "internal.h" 13 14 static const char afs_xattr_list[] = 15 "afs.acl\0" 16 "afs.cell\0" 17 "afs.fid\0" 18 "afs.volume\0" 19 "afs.yfs.acl\0" 20 "afs.yfs.acl_inherited\0" 21 "afs.yfs.acl_num_cleaned\0" 22 "afs.yfs.vol_acl"; 23 24 /* 25 * Retrieve a list of the supported xattrs. 26 */ 27 ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size) 28 { 29 if (size == 0) 30 return sizeof(afs_xattr_list); 31 if (size < sizeof(afs_xattr_list)) 32 return -ERANGE; 33 memcpy(buffer, afs_xattr_list, sizeof(afs_xattr_list)); 34 return sizeof(afs_xattr_list); 35 } 36 37 /* 38 * Get a file's ACL. 39 */ 40 static int afs_xattr_get_acl(const struct xattr_handler *handler, 41 struct dentry *dentry, 42 struct inode *inode, const char *name, 43 void *buffer, size_t size) 44 { 45 struct afs_fs_cursor fc; 46 struct afs_status_cb *scb; 47 struct afs_vnode *vnode = AFS_FS_I(inode); 48 struct afs_acl *acl = NULL; 49 struct key *key; 50 int ret = -ENOMEM; 51 52 scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS); 53 if (!scb) 54 goto error; 55 56 key = afs_request_key(vnode->volume->cell); 57 if (IS_ERR(key)) { 58 ret = PTR_ERR(key); 59 goto error_scb; 60 } 61 62 ret = -ERESTARTSYS; 63 if (afs_begin_vnode_operation(&fc, vnode, key, true)) { 64 afs_dataversion_t data_version = vnode->status.data_version; 65 66 while (afs_select_fileserver(&fc)) { 67 fc.cb_break = afs_calc_vnode_cb_break(vnode); 68 acl = afs_fs_fetch_acl(&fc, scb); 69 } 70 71 afs_check_for_remote_deletion(&fc, fc.vnode); 72 afs_vnode_commit_status(&fc, vnode, fc.cb_break, 73 &data_version, scb); 74 ret = afs_end_vnode_operation(&fc); 75 } 76 77 if (ret == 0) { 78 ret = acl->size; 79 if (size > 0) { 80 if (acl->size <= size) 81 memcpy(buffer, acl->data, acl->size); 82 else 83 ret = -ERANGE; 84 } 85 kfree(acl); 86 } 87 88 key_put(key); 89 error_scb: 90 kfree(scb); 91 error: 92 return ret; 93 } 94 95 /* 96 * Set a file's AFS3 ACL. 97 */ 98 static int afs_xattr_set_acl(const struct xattr_handler *handler, 99 struct dentry *dentry, 100 struct inode *inode, const char *name, 101 const void *buffer, size_t size, int flags) 102 { 103 struct afs_fs_cursor fc; 104 struct afs_status_cb *scb; 105 struct afs_vnode *vnode = AFS_FS_I(inode); 106 struct afs_acl *acl = NULL; 107 struct key *key; 108 int ret = -ENOMEM; 109 110 if (flags == XATTR_CREATE) 111 return -EINVAL; 112 113 scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS); 114 if (!scb) 115 goto error; 116 117 acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL); 118 if (!acl) 119 goto error_scb; 120 121 key = afs_request_key(vnode->volume->cell); 122 if (IS_ERR(key)) { 123 ret = PTR_ERR(key); 124 goto error_acl; 125 } 126 127 acl->size = size; 128 memcpy(acl->data, buffer, size); 129 130 ret = -ERESTARTSYS; 131 if (afs_begin_vnode_operation(&fc, vnode, key, true)) { 132 afs_dataversion_t data_version = vnode->status.data_version; 133 134 while (afs_select_fileserver(&fc)) { 135 fc.cb_break = afs_calc_vnode_cb_break(vnode); 136 afs_fs_store_acl(&fc, acl, scb); 137 } 138 139 afs_check_for_remote_deletion(&fc, fc.vnode); 140 afs_vnode_commit_status(&fc, vnode, fc.cb_break, 141 &data_version, scb); 142 ret = afs_end_vnode_operation(&fc); 143 } 144 145 key_put(key); 146 error_acl: 147 kfree(acl); 148 error_scb: 149 kfree(scb); 150 error: 151 return ret; 152 } 153 154 static const struct xattr_handler afs_xattr_afs_acl_handler = { 155 .name = "afs.acl", 156 .get = afs_xattr_get_acl, 157 .set = afs_xattr_set_acl, 158 }; 159 160 /* 161 * Get a file's YFS ACL. 162 */ 163 static int afs_xattr_get_yfs(const struct xattr_handler *handler, 164 struct dentry *dentry, 165 struct inode *inode, const char *name, 166 void *buffer, size_t size) 167 { 168 struct afs_fs_cursor fc; 169 struct afs_status_cb *scb; 170 struct afs_vnode *vnode = AFS_FS_I(inode); 171 struct yfs_acl *yacl = NULL; 172 struct key *key; 173 char buf[16], *data; 174 int which = 0, dsize, ret = -ENOMEM; 175 176 if (strcmp(name, "acl") == 0) 177 which = 0; 178 else if (strcmp(name, "acl_inherited") == 0) 179 which = 1; 180 else if (strcmp(name, "acl_num_cleaned") == 0) 181 which = 2; 182 else if (strcmp(name, "vol_acl") == 0) 183 which = 3; 184 else 185 return -EOPNOTSUPP; 186 187 yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL); 188 if (!yacl) 189 goto error; 190 191 if (which == 0) 192 yacl->flags |= YFS_ACL_WANT_ACL; 193 else if (which == 3) 194 yacl->flags |= YFS_ACL_WANT_VOL_ACL; 195 196 scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS); 197 if (!scb) 198 goto error_yacl; 199 200 key = afs_request_key(vnode->volume->cell); 201 if (IS_ERR(key)) { 202 ret = PTR_ERR(key); 203 goto error_scb; 204 } 205 206 ret = -ERESTARTSYS; 207 if (afs_begin_vnode_operation(&fc, vnode, key, true)) { 208 afs_dataversion_t data_version = vnode->status.data_version; 209 210 while (afs_select_fileserver(&fc)) { 211 fc.cb_break = afs_calc_vnode_cb_break(vnode); 212 yfs_fs_fetch_opaque_acl(&fc, yacl, scb); 213 } 214 215 afs_check_for_remote_deletion(&fc, fc.vnode); 216 afs_vnode_commit_status(&fc, vnode, fc.cb_break, 217 &data_version, scb); 218 ret = afs_end_vnode_operation(&fc); 219 } 220 221 if (ret < 0) 222 goto error_key; 223 224 switch (which) { 225 case 0: 226 data = yacl->acl->data; 227 dsize = yacl->acl->size; 228 break; 229 case 1: 230 data = buf; 231 dsize = scnprintf(buf, sizeof(buf), "%u", yacl->inherit_flag); 232 break; 233 case 2: 234 data = buf; 235 dsize = scnprintf(buf, sizeof(buf), "%u", yacl->num_cleaned); 236 break; 237 case 3: 238 data = yacl->vol_acl->data; 239 dsize = yacl->vol_acl->size; 240 break; 241 default: 242 ret = -EOPNOTSUPP; 243 goto error_key; 244 } 245 246 ret = dsize; 247 if (size > 0) { 248 if (dsize > size) { 249 ret = -ERANGE; 250 goto error_key; 251 } 252 memcpy(buffer, data, dsize); 253 } 254 255 error_key: 256 key_put(key); 257 error_scb: 258 kfree(scb); 259 error_yacl: 260 yfs_free_opaque_acl(yacl); 261 error: 262 return ret; 263 } 264 265 /* 266 * Set a file's YFS ACL. 267 */ 268 static int afs_xattr_set_yfs(const struct xattr_handler *handler, 269 struct dentry *dentry, 270 struct inode *inode, const char *name, 271 const void *buffer, size_t size, int flags) 272 { 273 struct afs_fs_cursor fc; 274 struct afs_status_cb *scb; 275 struct afs_vnode *vnode = AFS_FS_I(inode); 276 struct afs_acl *acl = NULL; 277 struct key *key; 278 int ret = -ENOMEM; 279 280 if (flags == XATTR_CREATE || 281 strcmp(name, "acl") != 0) 282 return -EINVAL; 283 284 scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS); 285 if (!scb) 286 goto error; 287 288 acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL); 289 if (!acl) 290 goto error_scb; 291 292 acl->size = size; 293 memcpy(acl->data, buffer, size); 294 295 key = afs_request_key(vnode->volume->cell); 296 if (IS_ERR(key)) { 297 ret = PTR_ERR(key); 298 goto error_acl; 299 } 300 301 ret = -ERESTARTSYS; 302 if (afs_begin_vnode_operation(&fc, vnode, key, true)) { 303 afs_dataversion_t data_version = vnode->status.data_version; 304 305 while (afs_select_fileserver(&fc)) { 306 fc.cb_break = afs_calc_vnode_cb_break(vnode); 307 yfs_fs_store_opaque_acl2(&fc, acl, scb); 308 } 309 310 afs_check_for_remote_deletion(&fc, fc.vnode); 311 afs_vnode_commit_status(&fc, vnode, fc.cb_break, 312 &data_version, scb); 313 ret = afs_end_vnode_operation(&fc); 314 } 315 316 error_acl: 317 kfree(acl); 318 key_put(key); 319 error_scb: 320 kfree(scb); 321 error: 322 return ret; 323 } 324 325 static const struct xattr_handler afs_xattr_yfs_handler = { 326 .prefix = "afs.yfs.", 327 .get = afs_xattr_get_yfs, 328 .set = afs_xattr_set_yfs, 329 }; 330 331 /* 332 * Get the name of the cell on which a file resides. 333 */ 334 static int afs_xattr_get_cell(const struct xattr_handler *handler, 335 struct dentry *dentry, 336 struct inode *inode, const char *name, 337 void *buffer, size_t size) 338 { 339 struct afs_vnode *vnode = AFS_FS_I(inode); 340 struct afs_cell *cell = vnode->volume->cell; 341 size_t namelen; 342 343 namelen = cell->name_len; 344 if (size == 0) 345 return namelen; 346 if (namelen > size) 347 return -ERANGE; 348 memcpy(buffer, cell->name, namelen); 349 return namelen; 350 } 351 352 static const struct xattr_handler afs_xattr_afs_cell_handler = { 353 .name = "afs.cell", 354 .get = afs_xattr_get_cell, 355 }; 356 357 /* 358 * Get the volume ID, vnode ID and vnode uniquifier of a file as a sequence of 359 * hex numbers separated by colons. 360 */ 361 static int afs_xattr_get_fid(const struct xattr_handler *handler, 362 struct dentry *dentry, 363 struct inode *inode, const char *name, 364 void *buffer, size_t size) 365 { 366 struct afs_vnode *vnode = AFS_FS_I(inode); 367 char text[16 + 1 + 24 + 1 + 8 + 1]; 368 size_t len; 369 370 /* The volume ID is 64-bit, the vnode ID is 96-bit and the 371 * uniquifier is 32-bit. 372 */ 373 len = scnprintf(text, sizeof(text), "%llx:", vnode->fid.vid); 374 if (vnode->fid.vnode_hi) 375 len += scnprintf(text + len, sizeof(text) - len, "%x%016llx", 376 vnode->fid.vnode_hi, vnode->fid.vnode); 377 else 378 len += scnprintf(text + len, sizeof(text) - len, "%llx", 379 vnode->fid.vnode); 380 len += scnprintf(text + len, sizeof(text) - len, ":%x", 381 vnode->fid.unique); 382 383 if (size == 0) 384 return len; 385 if (len > size) 386 return -ERANGE; 387 memcpy(buffer, text, len); 388 return len; 389 } 390 391 static const struct xattr_handler afs_xattr_afs_fid_handler = { 392 .name = "afs.fid", 393 .get = afs_xattr_get_fid, 394 }; 395 396 /* 397 * Get the name of the volume on which a file resides. 398 */ 399 static int afs_xattr_get_volume(const struct xattr_handler *handler, 400 struct dentry *dentry, 401 struct inode *inode, const char *name, 402 void *buffer, size_t size) 403 { 404 struct afs_vnode *vnode = AFS_FS_I(inode); 405 const char *volname = vnode->volume->name; 406 size_t namelen; 407 408 namelen = strlen(volname); 409 if (size == 0) 410 return namelen; 411 if (namelen > size) 412 return -ERANGE; 413 memcpy(buffer, volname, namelen); 414 return namelen; 415 } 416 417 static const struct xattr_handler afs_xattr_afs_volume_handler = { 418 .name = "afs.volume", 419 .get = afs_xattr_get_volume, 420 }; 421 422 const struct xattr_handler *afs_xattr_handlers[] = { 423 &afs_xattr_afs_acl_handler, 424 &afs_xattr_afs_cell_handler, 425 &afs_xattr_afs_fid_handler, 426 &afs_xattr_afs_volume_handler, 427 &afs_xattr_yfs_handler, /* afs.yfs. prefix */ 428 NULL 429 }; 430