move xattr permission checks into the VFS
Subsystems (2)
PATCH 2/8 move xattr permission checks into the VFS
The xattr code has rather complex permission checks because the rules are very different for different attribute namespaces. This patch moves as much as we can into the generic code. Currenyly all the major disk based filesystems duplicate these checks, while many minor filesystems or network filesystems lack some or all of them.
To do this we need defines for the extended attribute names in common code, I moved them up from JFS which had the nicest defintions.
fs/jfs/xattr.c +0 -15
@@ -83,21 +83,6 @@#define EA_NEW 0x0004#define EA_MALLOC 0x0008 -/* Namespaces */ -#define XATTR_SYSTEM_PREFIX "system." -#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1) - -#define XATTR_USER_PREFIX "user." -#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1) - -#define XATTR_OS2_PREFIX "os2." -#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1) - -/* XATTR_SECURITY_PREFIX is defined in include/linux/xattr.h */ -#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1) - -#define XATTR_TRUSTED_PREFIX "trusted." -#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1)/* * These three routines are used to recognize on-disk extended attributes
fs/xattr.c +57 -4
97 lines not on this page · raw message
include/linux/xattr.h +15 -0
@@ -13,7 +13,22 @@#define XATTR_CREATE 0x1/* set value, fail if attr already exists */ #define XATTR_REPLACE 0x2/* set value, fail if attr does not exist */ +/* Namespaces */ +#define XATTR_OS2_PREFIX "os2." +#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1) +#define XATTR_SECURITY_PREFIX "security." +#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1) + +#define XATTR_SYSTEM_PREFIX "system." +#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1) + +#define XATTR_TRUSTED_PREFIX "trusted." +#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1) + +#define XATTR_USER_PREFIX "user." +#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1) +struct xattr_handler {char *prefix;
Quoted 76 lines · Christoph Hellwig
The xattr code has rather complex permission checks because the rules are very different for different attribute namespaces. This patch moves as much as we can into the generic code. Currenyly all the major disk based filesystems duplicate these checks, while many minor filesystems or network filesystems lack some or all of them.
To do this we need defines for the extended attribute names in common code, I moved them up from JFS which had the nicest defintions.
Signed-off-by Christoph Hellwig <[email protected]>Index:
linux-2.6/fs/jfs/xattr.c
===================================================================fs/jfs/xattr.c +0
-15@@ -83,21 +83,6 @@#define EA_NEW 0x0004#define EA_MALLOC 0x0008 -/* Namespaces */ -#define XATTR_SYSTEM_PREFIX "system." -#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1) - -#define XATTR_USER_PREFIX "user." -#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1) - -#define XATTR_OS2_PREFIX "os2." -#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1) - -/* XATTR_SECURITY_PREFIX is defined in include/linux/xattr.h */ -#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1) - -#define XATTR_TRUSTED_PREFIX "trusted." -#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1)/* * These three routines are used to recognize on-disk extended attributes Index:
linux-2.6/fs/xattr.c
===================================================================fs/xattr.c +30
-0@@ -20,6 +20,47 @@#include <asm/uaccess.h> +/* +* Check permissions for extended attribute access. This is a bit complicated +* because different namespaces have very different rules. +*/ +static int +xattr_permission (struct inode *inode,const char *name,int mask) +{ +/* +* We can never set or remove an extended attribute on a read-only +* filesystem or on an immutable / append-only inode. +*/ +if (mask &MAY_WRITE ) { +if (IS_RDONLY (inode)) +return -EROFS ; +if (IS_IMMUTABLE (inode) ||IS_APPEND (inode)) +return -EPERM ; + } + +/* +* No restriction for security.* and system.* from the VFS. Decision +* on these is left to the underlying filesystem / security module. +*/ +if (!strncmp (name,XATTR_SECURITY_PREFIX ,XATTR_SECURITY_PREFIX_LEN ) || + !strncmp (name,XATTR_SYSTEM_PREFIX ,XATTR_SYSTEM_PREFIX_LEN )) +return 0 ; + +/* +* The trusted.* namespace can only accessed by a privilegued user. +*/ +if (!strncmp (name,XATTR_TRUSTED_PREFIX ,XATTR_TRUSTED_PREFIX_LEN ))
fs/xattr.c line 62
Quoted 10 lines
fs/xattr.c +10
-0+return (capable (CAP_SYS_ADMIN ) ?0 : -EPERM ); + +if (!strncmp (name,XATTR_USER_PREFIX ,XATTR_USER_PREFIX_LEN )) { +if (!S_ISREG (inode->i_mode) && + (!S_ISDIR (inode->i_mode) || inode->i_mode &S_ISVTX )) +return -EPERM ; + } + +return permission (inode, mask,NULL ); +}
The call to permission() here is not always applicable. Some filesystems may have different permissions when it comes to the right to read or set ACLs (both AFS and NFSv4, for instance, have such features).
For the NFSv4 client, therefore, I'd like to be able to override this particular check (and leave it up to the server to verify that we are authorised).
Cheers,
Trond
Quoted 12 lines · Trond Myklebust
fs/xattr.c line 47
Quoted 7 lines
fs/xattr.c +7
-0+/* +* No restriction for security.* and system.* from the VFS. Decision +* on these is left to the underlying filesystem / security module. +*/ +if (!strncmp (name,XATTR_SECURITY_PREFIX ,XATTR_SECURITY_PREFIX_LEN ) || + !strncmp (name,XATTR_SYSTEM_PREFIX ,XATTR_SYSTEM_PREFIX_LEN )) +return 0 ;The call to
permission()here is not always applicable. Some filesystems may have different permissions when it comes to the right to read or set ACLs (both AFS and NFSv4, for instance, have such features).
Quoted 3 lines
For the NFSv4 client, therefore, I'd like to be able to override this particular check (and leave it up to the server to verify that we are authorised).
See the code above. system namespace attributes (which ACLs are) are never handled in the VFS but always left to the filesystem.
Quoted 13 lines · Christoph Hellwig
Quoted 12 lines · Trond Myklebust
fs/xattr.c line 47
Quoted 7 lines
fs/xattr.c +7
-0+/* +* No restriction for security.* and system.* from the VFS. Decision +* on these is left to the underlying filesystem / security module. +*/ +if (!strncmp (name,XATTR_SECURITY_PREFIX ,XATTR_SECURITY_PREFIX_LEN ) || + !strncmp (name,XATTR_SYSTEM_PREFIX ,XATTR_SYSTEM_PREFIX_LEN )) +return 0 ;The call to
permission()here is not always applicable. Some filesystems may have different permissions when it comes to the right to read or set ACLs (both AFS and NFSv4, for instance, have such features).
Quoted 6 lines
Quoted 3 lines
For the NFSv4 client, therefore, I'd like to be able to override this particular check (and leave it up to the server to verify that we are authorised).
See the code above. system namespace attributes (which ACLs are) are never handled in the VFS but always left to the filesystem.
Ah... I see...
...but then I'm a bit confused w.r.t. your removal of the checks for S_ISREG(inode->i_mode) & friends in nfs4proc.c nfs4_setxattr(). You motivate the removal by the fact that you've moved those checks into the VFS, but AFAICS we will never hit the VFS checks for the case of system.nfs4_acl (which is the only case we care about right now).
Cheers,
Trond
Quoted 5 lines · Trond Myklebust
...but then I'm a bit confused w.r.t. your removal of the checks for
S_ISREG(inode->i_mode)& friends innfs4proc.cnfs4_setxattr(). You motivate the removal by the fact that you've moved those checks into the VFS, but AFAICS we will never hit the VFS checks for the case of system.nfs4_acl (which is the only case we care about right now).
Hmm, that's was at least half of an oversight. The other filesystems do exactly this check only for user ACLs. Posix ACLs are supported on all files but links and in the other filesystems these link checks are hidden much deeper in the callchanin.
If this check is the right thing for NFSv4 ACLs we should drop the nfs patch.