Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Make 'check_acl()' a first-class filesystem op

This is stage one in flattening out the callchains for the common
permission testing. Rather than have most filesystem implement their
own inode->i_op->permission function that just calls back down to the
VFS layers 'generic_permission()' with the per-filesystem ACL checking
function, the filesystem can just expose its 'check_acl' function
directly, and let the VFS layer do everything for it.

This is all just preparatory - no filesystem actually enables this yet.

Reviewed-by: James Morris <jmorris@namei.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+42 -33
+41 -33
fs/namei.c
··· 169 169 EXPORT_SYMBOL(putname); 170 170 #endif 171 171 172 + /* 173 + * This does basic POSIX ACL permission checking 174 + */ 175 + static int acl_permission_check(struct inode *inode, int mask, 176 + int (*check_acl)(struct inode *inode, int mask)) 177 + { 178 + umode_t mode = inode->i_mode; 179 + 180 + mask &= MAY_READ | MAY_WRITE | MAY_EXEC; 181 + 182 + if (current_fsuid() == inode->i_uid) 183 + mode >>= 6; 184 + else { 185 + if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) { 186 + int error = check_acl(inode, mask); 187 + if (error != -EAGAIN) 188 + return error; 189 + } 190 + 191 + if (in_group_p(inode->i_gid)) 192 + mode >>= 3; 193 + } 194 + 195 + /* 196 + * If the DACs are ok we don't need any capability check. 197 + */ 198 + if ((mask & ~mode) == 0) 199 + return 0; 200 + return -EACCES; 201 + } 172 202 173 203 /** 174 204 * generic_permission - check for access rights on a Posix-like filesystem ··· 214 184 int generic_permission(struct inode *inode, int mask, 215 185 int (*check_acl)(struct inode *inode, int mask)) 216 186 { 217 - umode_t mode = inode->i_mode; 218 - 219 - mask &= MAY_READ | MAY_WRITE | MAY_EXEC; 220 - 221 - if (current_fsuid() == inode->i_uid) 222 - mode >>= 6; 223 - else { 224 - if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) { 225 - int error = check_acl(inode, mask); 226 - if (error == -EACCES) 227 - goto check_capabilities; 228 - else if (error != -EAGAIN) 229 - return error; 230 - } 231 - 232 - if (in_group_p(inode->i_gid)) 233 - mode >>= 3; 234 - } 187 + int ret; 235 188 236 189 /* 237 - * If the DACs are ok we don't need any capability check. 190 + * Do the basic POSIX ACL permission checks. 238 191 */ 239 - if ((mask & ~mode) == 0) 240 - return 0; 192 + ret = acl_permission_check(inode, mask, check_acl); 193 + if (ret != -EACCES) 194 + return ret; 241 195 242 - check_capabilities: 243 196 /* 244 197 * Read/write DACs are always overridable. 245 198 * Executable DACs are overridable if at least one exec bit is set. ··· 275 262 if (inode->i_op->permission) 276 263 retval = inode->i_op->permission(inode, mask); 277 264 else 278 - retval = generic_permission(inode, mask, NULL); 265 + retval = generic_permission(inode, mask, inode->i_op->check_acl); 279 266 280 267 if (retval) 281 268 return retval; ··· 445 432 */ 446 433 static int exec_permission_lite(struct inode *inode) 447 434 { 448 - umode_t mode = inode->i_mode; 435 + int ret; 449 436 450 437 if (inode->i_op->permission) { 451 - int ret = inode->i_op->permission(inode, MAY_EXEC); 438 + ret = inode->i_op->permission(inode, MAY_EXEC); 452 439 if (!ret) 453 440 goto ok; 454 441 return ret; 455 442 } 456 - 457 - if (current_fsuid() == inode->i_uid) 458 - mode >>= 6; 459 - else if (in_group_p(inode->i_gid)) 460 - mode >>= 3; 461 - 462 - if (mode & MAY_EXEC) 443 + ret = acl_permission_check(inode, MAY_EXEC, inode->i_op->check_acl); 444 + if (!ret) 463 445 goto ok; 464 446 465 447 if (capable(CAP_DAC_OVERRIDE) || capable(CAP_DAC_READ_SEARCH)) 466 448 goto ok; 467 449 468 - return -EACCES; 450 + return ret; 469 451 ok: 470 452 return security_inode_permission(inode, MAY_EXEC); 471 453 }
+1
include/linux/fs.h
··· 1528 1528 void (*put_link) (struct dentry *, struct nameidata *, void *); 1529 1529 void (*truncate) (struct inode *); 1530 1530 int (*permission) (struct inode *, int); 1531 + int (*check_acl)(struct inode *, int); 1531 1532 int (*setattr) (struct dentry *, struct iattr *); 1532 1533 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); 1533 1534 int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);