acl.c (37bc15392a2363ca822b2c2828e0ccafbea32f75) | acl.c (64e178a7118b1cf7648391755e44dcc209091003) |
---|---|
1/* 2 * linux/fs/ext4/acl.c 3 * 4 * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> 5 */ 6 7#include <linux/init.h> 8#include <linux/sched.h> --- 138 unchanged lines hidden (view full) --- 147struct posix_acl * 148ext4_get_acl(struct inode *inode, int type) 149{ 150 int name_index; 151 char *value = NULL; 152 struct posix_acl *acl; 153 int retval; 154 | 1/* 2 * linux/fs/ext4/acl.c 3 * 4 * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> 5 */ 6 7#include <linux/init.h> 8#include <linux/sched.h> --- 138 unchanged lines hidden (view full) --- 147struct posix_acl * 148ext4_get_acl(struct inode *inode, int type) 149{ 150 int name_index; 151 char *value = NULL; 152 struct posix_acl *acl; 153 int retval; 154 |
155 if (!test_opt(inode->i_sb, POSIX_ACL)) 156 return NULL; 157 158 acl = get_cached_acl(inode, type); 159 if (acl != ACL_NOT_CACHED) 160 return acl; 161 | |
162 switch (type) { 163 case ACL_TYPE_ACCESS: 164 name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; 165 break; 166 case ACL_TYPE_DEFAULT: 167 name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT; 168 break; 169 default: --- 21 unchanged lines hidden (view full) --- 191} 192 193/* 194 * Set the access or default ACL of an inode. 195 * 196 * inode->i_mutex: down unless called from ext4_new_inode 197 */ 198static int | 155 switch (type) { 156 case ACL_TYPE_ACCESS: 157 name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; 158 break; 159 case ACL_TYPE_DEFAULT: 160 name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT; 161 break; 162 default: --- 21 unchanged lines hidden (view full) --- 184} 185 186/* 187 * Set the access or default ACL of an inode. 188 * 189 * inode->i_mutex: down unless called from ext4_new_inode 190 */ 191static int |
199ext4_set_acl(handle_t *handle, struct inode *inode, int type, | 192__ext4_set_acl(handle_t *handle, struct inode *inode, int type, |
200 struct posix_acl *acl) 201{ 202 int name_index; 203 void *value = NULL; 204 size_t size = 0; 205 int error; 206 | 193 struct posix_acl *acl) 194{ 195 int name_index; 196 void *value = NULL; 197 size_t size = 0; 198 int error; 199 |
207 if (S_ISLNK(inode->i_mode)) 208 return -EOPNOTSUPP; 209 | |
210 switch (type) { 211 case ACL_TYPE_ACCESS: 212 name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; 213 if (acl) { 214 error = posix_acl_equiv_mode(acl, &inode->i_mode); 215 if (error < 0) 216 return error; 217 else { --- 25 unchanged lines hidden (view full) --- 243 244 kfree(value); 245 if (!error) 246 set_cached_acl(inode, type, acl); 247 248 return error; 249} 250 | 200 switch (type) { 201 case ACL_TYPE_ACCESS: 202 name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; 203 if (acl) { 204 error = posix_acl_equiv_mode(acl, &inode->i_mode); 205 if (error < 0) 206 return error; 207 else { --- 25 unchanged lines hidden (view full) --- 233 234 kfree(value); 235 if (!error) 236 set_cached_acl(inode, type, acl); 237 238 return error; 239} 240 |
251/* 252 * Initialize the ACLs of a new inode. Called from ext4_new_inode. 253 * 254 * dir->i_mutex: down 255 * inode->i_mutex: up (access to inode is still exclusive) 256 */ | |
257int | 241int |
258ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) | 242ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type) |
259{ | 243{ |
260 struct posix_acl *acl = NULL; 261 int error = 0; 262 263 if (!S_ISLNK(inode->i_mode)) { 264 if (test_opt(dir->i_sb, POSIX_ACL)) { 265 acl = ext4_get_acl(dir, ACL_TYPE_DEFAULT); 266 if (IS_ERR(acl)) 267 return PTR_ERR(acl); 268 } 269 if (!acl) 270 inode->i_mode &= ~current_umask(); 271 } 272 if (test_opt(inode->i_sb, POSIX_ACL) && acl) { 273 if (S_ISDIR(inode->i_mode)) { 274 error = ext4_set_acl(handle, inode, 275 ACL_TYPE_DEFAULT, acl); 276 if (error) 277 goto cleanup; 278 } 279 error = __posix_acl_create(&acl, GFP_NOFS, &inode->i_mode); 280 if (error < 0) 281 return error; 282 283 if (error > 0) { 284 /* This is an extended ACL */ 285 error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, acl); 286 } 287 } 288cleanup: 289 posix_acl_release(acl); 290 return error; 291} 292 293/* 294 * Does chmod for an inode that may have an Access Control List. The 295 * inode->i_mode field must be updated to the desired value by the caller 296 * before calling this function. 297 * Returns 0 on success, or a negative error number. 298 * 299 * We change the ACL rather than storing some ACL entries in the file 300 * mode permission bits (which would be more efficient), because that 301 * would break once additional permissions (like ACL_APPEND, ACL_DELETE 302 * for directories) are added. There are no more bits available in the 303 * file mode. 304 * 305 * inode->i_mutex: down 306 */ 307int 308ext4_acl_chmod(struct inode *inode) 309{ 310 struct posix_acl *acl; | |
311 handle_t *handle; | 244 handle_t *handle; |
312 int retries = 0; 313 int error; | 245 int error, retries = 0; |
314 | 246 |
315 316 if (S_ISLNK(inode->i_mode)) 317 return -EOPNOTSUPP; 318 if (!test_opt(inode->i_sb, POSIX_ACL)) 319 return 0; 320 acl = ext4_get_acl(inode, ACL_TYPE_ACCESS); 321 if (IS_ERR(acl) || !acl) 322 return PTR_ERR(acl); 323 error = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); 324 if (error) 325 return error; | |
326retry: 327 handle = ext4_journal_start(inode, EXT4_HT_XATTR, 328 ext4_jbd2_credits_xattr(inode)); | 247retry: 248 handle = ext4_journal_start(inode, EXT4_HT_XATTR, 249 ext4_jbd2_credits_xattr(inode)); |
329 if (IS_ERR(handle)) { 330 error = PTR_ERR(handle); 331 ext4_std_error(inode->i_sb, error); 332 goto out; 333 } 334 error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, acl); | 250 if (IS_ERR(handle)) 251 return PTR_ERR(handle); 252 253 error = __ext4_set_acl(handle, inode, type, acl); |
335 ext4_journal_stop(handle); | 254 ext4_journal_stop(handle); |
336 if (error == -ENOSPC && 337 ext4_should_retry_alloc(inode->i_sb, &retries)) | 255 if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) |
338 goto retry; | 256 goto retry; |
339out: 340 posix_acl_release(acl); | |
341 return error; 342} 343 344/* | 257 return error; 258} 259 260/* |
345 * Extended attribute handlers | 261 * Initialize the ACLs of a new inode. Called from ext4_new_inode. 262 * 263 * dir->i_mutex: down 264 * inode->i_mutex: up (access to inode is still exclusive) |
346 */ | 265 */ |
347static size_t 348ext4_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_len, 349 const char *name, size_t name_len, int type) | 266int 267ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) |
350{ | 268{ |
351 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS); 352 353 if (!test_opt(dentry->d_sb, POSIX_ACL)) 354 return 0; 355 if (list && size <= list_len) 356 memcpy(list, POSIX_ACL_XATTR_ACCESS, size); 357 return size; 358} 359 360static size_t 361ext4_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_len, 362 const char *name, size_t name_len, int type) 363{ 364 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT); 365 366 if (!test_opt(dentry->d_sb, POSIX_ACL)) 367 return 0; 368 if (list && size <= list_len) 369 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size); 370 return size; 371} 372 373static int 374ext4_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer, 375 size_t size, int type) 376{ 377 struct posix_acl *acl; | 269 struct posix_acl *default_acl, *acl; |
378 int error; 379 | 270 int error; 271 |
380 if (strcmp(name, "") != 0) 381 return -EINVAL; 382 if (!test_opt(dentry->d_sb, POSIX_ACL)) 383 return -EOPNOTSUPP; | 272 error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl); 273 if (error) 274 return error; |
384 | 275 |
385 acl = ext4_get_acl(dentry->d_inode, type); 386 if (IS_ERR(acl)) 387 return PTR_ERR(acl); 388 if (acl == NULL) 389 return -ENODATA; 390 error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); 391 posix_acl_release(acl); 392 393 return error; 394} 395 396static int 397ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, 398 size_t size, int flags, int type) 399{ 400 struct inode *inode = dentry->d_inode; 401 handle_t *handle; 402 struct posix_acl *acl; 403 int error, retries = 0; 404 405 if (strcmp(name, "") != 0) 406 return -EINVAL; 407 if (!test_opt(inode->i_sb, POSIX_ACL)) 408 return -EOPNOTSUPP; 409 if (!inode_owner_or_capable(inode)) 410 return -EPERM; 411 412 if (value) { 413 acl = posix_acl_from_xattr(&init_user_ns, value, size); 414 if (IS_ERR(acl)) 415 return PTR_ERR(acl); 416 else if (acl) { 417 error = posix_acl_valid(acl); 418 if (error) 419 goto release_and_out; 420 } 421 } else 422 acl = NULL; 423 424retry: 425 handle = ext4_journal_start(inode, EXT4_HT_XATTR, 426 ext4_jbd2_credits_xattr(inode)); 427 if (IS_ERR(handle)) { 428 error = PTR_ERR(handle); 429 goto release_and_out; | 276 if (default_acl) { 277 error = __ext4_set_acl(handle, inode, ACL_TYPE_DEFAULT, 278 default_acl); 279 posix_acl_release(default_acl); |
430 } | 280 } |
431 error = ext4_set_acl(handle, inode, type, acl); 432 ext4_journal_stop(handle); 433 if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) 434 goto retry; 435 436release_and_out: 437 posix_acl_release(acl); | 281 if (acl) { 282 if (!error) 283 error = __ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, 284 acl); 285 posix_acl_release(acl); 286 } |
438 return error; 439} | 287 return error; 288} |
440 441const struct xattr_handler ext4_xattr_acl_access_handler = { 442 .prefix = POSIX_ACL_XATTR_ACCESS, 443 .flags = ACL_TYPE_ACCESS, 444 .list = ext4_xattr_list_acl_access, 445 .get = ext4_xattr_get_acl, 446 .set = ext4_xattr_set_acl, 447}; 448 449const struct xattr_handler ext4_xattr_acl_default_handler = { 450 .prefix = POSIX_ACL_XATTR_DEFAULT, 451 .flags = ACL_TYPE_DEFAULT, 452 .list = ext4_xattr_list_acl_default, 453 .get = ext4_xattr_get_acl, 454 .set = ext4_xattr_set_acl, 455}; | |