lNFS: 3.7 port
Subsystems (5)
cover lNFS: 3.7 port
I basically reworked the code in the following areas:
1) Forward ported to Linux 3.7 kernel
2) Separated the server patches from the client patches
3) Eliminated the need for the previous two clean up patches
4) Eliminated a large number of #ifdefs
Dave Quigley (2):
NFS:Add labels to client function prototypes
NFS: Add label lifecycle management
David Quigley (10):
Security: Add hook to calculate context based on a negative dentry.
Security: Add Hook to test if the particular xattr is part of a MAC
model.
LSM: Add flags field to security_sb_set_mnt_opts for in kernel mount
data.
SELinux: Add new labeling type native labels
KConfig: Add KConfig entries for Labeled NFS
NFSv4: Add label recommended attribute and NFSv4 flags
NFSv4: Introduce new label structure
NFSv4: Extend fattr bitmaps to support all 3 words
NFS: Client implementation of Labeled-NFS
NFSD: Server implementation of MAC Labeling
fs/nfs/Kconfig | 16 + fs/nfs/client.c | 2 +- fs/nfs/dir.c | 49 ++- fs/nfs/getroot.c | 2 +- fs/nfs/inode.c | 140 +++++++-- fs/nfs/namespace.c | 2 +- fs/nfs/nfs3acl.c | 4 +- fs/nfs/nfs3proc.c | 41 +-- fs/nfs/nfs4_fs.h | 8 +- fs/nfs/nfs4namespace.c | 2 +- fs/nfs/nfs4proc.c | 574 ++++++++++++++++++++++++++++++++---- fs/nfs/nfs4xdr.c | 198 ++++++++++--- fs/nfs/proc.c | 15 +- fs/nfs/super.c | 17 +- fs/nfsd/Kconfig | 13 + fs/nfsd/nfs4proc.c | 33 +++ fs/nfsd/nfs4xdr.c | 115 +++++++- fs/nfsd/nfsd.h | 8 +- fs/nfsd/vfs.c | 31 ++ fs/nfsd/vfs.h | 2 + fs/nfsd/xdr4.h | 3 + include/linux/nfs4.h | 9 + include/linux/nfs_fs.h | 28 +- include/linux/nfs_fs_sb.h | 10 +- include/linux/nfs_xdr.h | 30 +- include/linux/security.h | 57 +++- include/uapi/linux/nfs4.h | 1 + security/capability.c | 19 +- security/security.c | 24 +- security/selinux/hooks.c | 92 +++++- security/selinux/include/security.h | 2 + security/selinux/ss/policydb.c | 5 +- security/smack/smack_lsm.c | 11 + 33 files changed, 1360 insertions(+), 203 deletions(-)
Signature · 1 line
1.7.11.7
PATCH 1/12 Security: Add hook to calculate context based on a negative dentry.
From: David Quigley <[email protected]>
There is a time where we need to calculate a context without the inode having been created yet. To do this we take the negative dentry and calculate a context based on the process and the parent directory contexts.
--- include/linux/security.h | 27 +++++++++++++++++++++++++++ security/capability.c | 8 ++++++++ security/security.c | 10 ++++++++++ security/selinux/hooks.c | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+)
include/linux/security.h +27 -0
@@ -26,6 +26,7 @@#include <linux/capability.h> #include <linux/slab.h> #include <linux/err.h> +#include <linux/string.h> struct linux_binprm ;struct cred ;
@@ -306,6 +307,15 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)* Parse a string of security data filling in the opts structure * @options string containing all mount options known by the LSM * @opts binary data structure usable by the LSM +* @dentry_init_security: +* Compute a context for a dentry as the inode is not yet available +* since NFSv4 has no label backed by an EA anyway. +* @dentry dentry to use in calculating the context. +* @mode mode used to determine resource type. +* @name name of the last path component used to create file +* @ctx pointer to place the pointer to the resulting context in. +* @ctxlen point to place the length of the resulting context. +* * * Security hooks for inode operations. *
@@ -1427,6 +1437,10 @@ struct security_operations {void (*sb_clone_mnt_opts) (const struct super_block *oldsb,struct super_block *newsb);int (*sb_parse_opts_str) (char *options,struct security_mnt_opts *opts); +int (*dentry_init_security) (struct dentry *dentry,int mode, +struct qstr *name,void **ctx, +u32 *ctxlen); +#ifdef CONFIG_SECURITY_PATH int (*path_unlink) (struct path *dir,struct dentry *dentry);
@@ -1709,6 +1723,9 @@ int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *ovoid security_sb_clone_mnt_opts (const struct super_block *oldsb,struct super_block *newsb);int security_sb_parse_opts_str (char *options,struct security_mnt_opts *opts); +int security_dentry_init_security (struct dentry *dentry,int mode, +struct qstr *name,void **ctx, +u32 *ctxlen);int security_inode_alloc (struct inode *inode);void security_inode_free (struct inode *inode);
@@ -2013,6 +2030,16 @@ static inline int security_inode_alloc(struct inode *inode)static inline void security_inode_free (struct inode *inode) { } +static inline int security_dentry_init_security (struct dentry *dentry, +int mode, +struct qstr *name, +void **ctx, +u32 *ctxlen) +{ +return -EOPNOTSUPP ; +} + + static inline int security_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr,
security/capability.c +8 -0
@@ -108,6 +108,13 @@ static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)return 0 ; } +static int cap_dentry_init_security (struct dentry *dentry,int mode, +struct qstr *name,void **ctx, +u32 *ctxlen) +{ +return 0 ; +} +static int cap_inode_alloc_security (struct inode *inode) {return 0 ;
@@ -910,6 +917,7 @@ void __init security_fixup_ops(struct security_operations *ops)set_to_cap_if_null (ops, sb_set_mnt_opts);set_to_cap_if_null (ops, sb_clone_mnt_opts);set_to_cap_if_null (ops, sb_parse_opts_str); +set_to_cap_if_null (ops, dentry_init_security);set_to_cap_if_null (ops, inode_alloc_security);set_to_cap_if_null (ops, inode_free_security);set_to_cap_if_null (ops, inode_init_security);
security/security.c +10 -0
@@ -12,6 +12,7 @@*/ #include <linux/capability.h> +#include <linux/dcache.h> #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h>
@@ -324,6 +325,15 @@ void security_inode_free(struct inode *inode) security_ops->inode_free_security (inode); } +int security_dentry_init_security (struct dentry *dentry,int mode, +struct qstr *name,void **ctx, +u32 *ctxlen) +{ +return security_ops->dentry_init_security (dentry, mode, name, + ctx, ctxlen); +} +EXPORT_SYMBOL (security_dentry_init_security); +int security_inode_init_security (struct inode *inode,struct inode *dir,const struct qstr *qstr,const initxattrs initxattrs,void *fs_data)
security/selinux/hooks.c +35 -0
@@ -2483,6 +2483,40 @@ static void selinux_inode_free_security(struct inode *inode)inode_free_security (inode); } +static int selinux_dentry_init_security (struct dentry *dentry,int mode, +struct qstr *name,void **ctx, +u32 *ctxlen) +{ +struct cred *cred =current_cred (); +struct task_security_struct *tsec; +struct inode_security_struct *dsec; +struct superblock_security_struct *sbsec; +struct inode *dir = dentry->d_parent->d_inode; +u32 newsid; +int rc; + + tsec = cred->security; + dsec = dir->i_security; + sbsec = dir->i_sb->s_security; + +if (tsec->create_sid && sbsec->behavior !=SECURITY_FS_USE_MNTPOINT ) { + newsid = tsec->create_sid; + }else { + rc =security_transition_sid (tsec->sid, dsec->sid, +inode_mode_to_security_class (mode), + name, + &newsid); +if (rc) { +printk (KERN_WARNING +"%s: security_transition_sid failed, rc=%d\n" , + __func__, -rc); +return rc; + } + } + +return security_sid_to_context (newsid, (char **)ctx, ctxlen); +} +static int selinux_inode_init_security (struct inode *inode,struct inode *dir,const struct qstr *qstr,char **name,void **value,size_t *len)
@@ -5509,6 +5543,7 @@ static struct security_operations selinux_ops = { .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, .sb_parse_opts_str = selinux_parse_opts_str, + .dentry_init_security = selinux_dentry_init_security, .inode_alloc_security = selinux_inode_alloc_security, .inode_free_security = selinux_inode_free_security,
Signature · 1 line
1.7.11.7
PATCH 2/12 Security: Add Hook to test if the particular xattr is part of a MAC model.
In reply to Steve DicksonFrom: David Quigley <[email protected]>
The interface to request security labels from user space is the xattr interface. When requesting the security label from an NFS server it is important to make sure the requested xattr actually is a MAC label. This allows us to make sure that we get the desired semantics from the attribute instead of something else such as capabilities or a time based LSM.
--- include/linux/security.h | 14 ++++++++++++++ security/capability.c | 6 ++++++ security/security.c | 6 ++++++ security/selinux/hooks.c | 6 ++++++ security/smack/smack_lsm.c | 11 +++++++++++ 5 files changed, 43 insertions(+)
include/linux/security.h +14 -0
@@ -1307,6 +1307,13 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)* @pages contains the number of pages. * Return 0 if permission is granted. * +* @ismaclabel: +* Check if the extended attribute specified by @name +* represents a MAC label. Returns 0 if name is a MAC +* attribute otherwise returns non-zero. +* @name full extended attribute name to check against +* LSM as a MAC label. +* * @secid_to_secctx: * Convert secid to security context. If secdata is NULL the length of * the result will be returned in seclen, but no secdata will be returned.
@@ -1588,6 +1595,7 @@ struct security_operations {int (*getprocattr) (struct task_struct *p,char *name,char **value);int (*setprocattr) (struct task_struct *p,char *name,void *value,size_t size); +int (*ismaclabel) (const char *name);int (*secid_to_secctx) (u32 secid,char **secdata,u32 *seclen);int (*secctx_to_secid) (const char *secdata,u32 seclen,u32 *secid);void (*release_secctx) (char *secdata,u32 seclen);
@@ -1837,6 +1845,7 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode);int security_getprocattr (struct task_struct *p,char *name,char **value);int security_setprocattr (struct task_struct *p,char *name,void *value,size_t size);int security_netlink_send (struct sock *sk,struct sk_buff *skb); +int security_ismaclabel (const char *name);int security_secid_to_secctx (u32 secid,char **secdata,u32 *seclen);int security_secctx_to_secid (const char *secdata,u32 seclen,u32 *secid);void security_release_secctx (char *secdata,u32 seclen);
@@ -2525,6 +2534,11 @@ static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb)return cap_netlink_send (sk, skb); } +static inline int security_ismaclabel (const char *name) +{ +return 0 ; +} +static inline int security_secid_to_secctx (u32 secid,char **secdata,u32 *seclen) {return -EOPNOTSUPP ;
security/capability.c +6 -0
@@ -802,6 +802,11 @@ static int cap_setprocattr(struct task_struct *p, char *name, void *value,return -EINVAL ; } +static int cap_ismaclabel (const char *name) +{ +return 0 ; +} +static int cap_secid_to_secctx (u32 secid,char **secdata,u32 *seclen) {return -EOPNOTSUPP ;
@@ -1021,6 +1026,7 @@ void __init security_fixup_ops(struct security_operations *ops)set_to_cap_if_null (ops, d_instantiate);set_to_cap_if_null (ops, getprocattr);set_to_cap_if_null (ops, setprocattr); +set_to_cap_if_null (ops, ismaclabel);set_to_cap_if_null (ops, secid_to_secctx);set_to_cap_if_null (ops, secctx_to_secid);set_to_cap_if_null (ops, release_secctx);
security/security.c +6 -0
@@ -1057,6 +1057,12 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb)return security_ops->netlink_send (sk, skb); } +int security_ismaclabel (const char *name) +{ +return security_ops->ismaclabel (name); +} +EXPORT_SYMBOL (security_ismaclabel); +int security_secid_to_secctx (u32 secid,char **secdata,u32 *seclen) {return security_ops->secid_to_secctx (secid, secdata, seclen);
security/selinux/hooks.c +6 -0
@@ -5401,6 +5401,11 @@ abort_change:return error; } +static int selinux_ismaclabel (const char *name) +{ +return (strcmp (name,XATTR_SELINUX_SUFFIX ) ==0 ); +} +static int selinux_secid_to_secctx (u32 secid,char **secdata,u32 *seclen) {return security_sid_to_context (secid, secdata, seclen);
@@ -5639,6 +5644,7 @@ static struct security_operations selinux_ops = { .getprocattr = selinux_getprocattr, .setprocattr = selinux_setprocattr, + .ismaclabel = selinux_ismaclabel, .secid_to_secctx = selinux_secid_to_secctx, .secctx_to_secid = selinux_secctx_to_secid, .release_secctx = selinux_release_secctx,
security/smack/smack_lsm.c +11 -0
@@ -3335,6 +3335,16 @@ static void smack_audit_rule_free(void *vrule)#endif /* CONFIG_AUDIT */ /** +* smack_ismaclabel - check if xattr @name references a smack MAC label +* @name: Full xattr name to check. +*/ +static int smack_ismaclabel (const char *name) +{ +return (strcmp (name,XATTR_SMACK_SUFFIX ) ==0 ); +} + + +/** * smack_secid_to_secctx - return the smack label for a secid * @secid: incoming integer * @secdata: destination
@@ -3530,6 +3540,7 @@ struct security_operations smack_ops = { .audit_rule_free = smack_audit_rule_free,#endif /* CONFIG_AUDIT */ + .ismaclabel = smack_ismaclabel, .secid_to_secctx = smack_secid_to_secctx, .secctx_to_secid = smack_secctx_to_secid, .release_secctx = smack_release_secctx,
Signature · 1 line
1.7.11.7
PATCH 3/12 LSM: Add flags field to security_sb_set_mnt_opts for in kernel mount data.
In reply to Steve DicksonFrom: David Quigley <[email protected]>
There is no way to differentiate if a text mount option is passed from user space or the kernel. A flags field is being added to the security_sb_set_mnt_opts hook to allow for in kernel security flags to be sent to the LSM for processing in addition to the text options received from mount. This patch also updated existing code to fix compilation errors.
--- fs/nfs/super.c | 3 ++- include/linux/security.h | 13 ++++++++++--- security/capability.c | 5 ++++- security/security.c | 7 +++++-- security/selinux/hooks.c | 12 ++++++++++-- 5 files changed, 31 insertions(+), 9 deletions(-)
fs/nfs/super.c +2 -1
@@ -2418,7 +2418,8 @@ static int nfs_bdi_register(struct nfs_server *server)int nfs_set_sb_security (struct super_block *s,struct dentry *mntroot,struct nfs_mount_info *mount_info) { -return security_sb_set_mnt_opts (s, &mount_info->parsed->lsm_opts); +return security_sb_set_mnt_opts (s, &mount_info->parsed->lsm_opts, +0 ,NULL ); }EXPORT_SYMBOL_GPL (nfs_set_sb_security);
include/linux/security.h +10 -3
@@ -1440,7 +1440,9 @@ struct security_operations {int (*sb_pivotroot) (struct path *old_path,struct path *new_path);int (*sb_set_mnt_opts) (struct super_block *sb, -struct security_mnt_opts *opts); +struct security_mnt_opts *opts, +unsigned long kern_flags, +unsigned long *set_kern_flags);void (*sb_clone_mnt_opts) (const struct super_block *oldsb,struct super_block *newsb);int (*sb_parse_opts_str) (char *options,struct security_mnt_opts *opts);
@@ -1727,7 +1729,10 @@ int security_sb_mount(const char *dev_name, struct path *path, const char *type, unsigned long flags, void *data);int security_sb_umount (struct vfsmount *mnt,int flags);int security_sb_pivotroot (struct path *old_path,struct path *new_path); -int security_sb_set_mnt_opts (struct super_block *sb,struct security_mnt_opts *opts); +int security_sb_set_mnt_opts (struct super_block *sb, +struct security_mnt_opts *opts, +unsigned long kern_flags, +unsigned long *set_kern_flags);void security_sb_clone_mnt_opts (const struct super_block *oldsb,struct super_block *newsb);int security_sb_parse_opts_str (char *options,struct security_mnt_opts *opts);
@@ -2017,7 +2022,9 @@ static inline int security_sb_pivotroot(struct path *old_path, }static inline int security_sb_set_mnt_opts (struct super_block *sb, -struct security_mnt_opts *opts) +struct security_mnt_opts *opts, +unsigned long kern_flags, +unsigned long *set_kern_flags) {return 0 ; }
security/capability.c +4 -1
@@ -91,7 +91,10 @@ static int cap_sb_pivotroot(struct path *old_path, struct path *new_path) }static int cap_sb_set_mnt_opts (struct super_block *sb, -struct security_mnt_opts *opts) +struct security_mnt_opts *opts, +unsigned long kern_flags, +unsigned long *set_kern_flags) + {if (unlikely (opts->num_mnt_opts))return -EOPNOTSUPP ;
security/security.c +5 -2
@@ -294,9 +294,12 @@ int security_sb_pivotroot(struct path *old_path, struct path *new_path) }int security_sb_set_mnt_opts (struct super_block *sb, -struct security_mnt_opts *opts) +struct security_mnt_opts *opts, +unsigned long kern_flags, +unsigned long *set_kern_flags) { -return security_ops->sb_set_mnt_opts (sb, opts); +return security_ops->sb_set_mnt_opts (sb, opts, kern_flags, + set_kern_flags); }EXPORT_SYMBOL (security_sb_set_mnt_opts);
security/selinux/hooks.c +10 -2
@@ -551,7 +551,9 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,* labeling information. */ static int selinux_set_mnt_opts (struct super_block *sb, -struct security_mnt_opts *opts) +struct security_mnt_opts *opts, +unsigned long kern_flags, +unsigned long *set_kern_flags) {const struct cred *cred =current_cred ();int rc =0 , i;
@@ -579,6 +581,12 @@ static int selinux_set_mnt_opts(struct super_block *sb, "before the security server is initialized\n"); goto out; } +if (kern_flags && !set_kern_flags) { +/* Specifying internal flags without providing a place to +* place the results is not allowed */ + rc = -EINVAL ; + goto out; + }/* * Binary mount data FS will come through this function twice. Once
@@ -948,7 +956,7 @@ static int superblock_doinit(struct super_block *sb, void *data) goto out_err; out: - rc =selinux_set_mnt_opts (sb, &opts); + rc =selinux_set_mnt_opts (sb, &opts,0 ,NULL ); out_err:security_free_mnt_opts (&opts);
Signature · 1 line
1.7.11.7
PATCH 4/12 SELinux: Add new labeling type native labels
In reply to Steve DicksonFrom: David Quigley <[email protected]>
There currently doesn't exist a labeling type that is adequate for use with labeled NFS. Since NFS doesn't really support xattrs we can't use the use xattr labeling behavior. For this we developed a new labeling type. The native labeling type is used solely by NFS to ensure NFS inodes are labeled at runtime by the NFS code instead of relying on the SELinux security server on the client end.
--- include/linux/security.h | 3 +++ security/selinux/hooks.c | 35 ++++++++++++++++++++++++++--------- security/selinux/include/security.h | 2 ++ security/selinux/ss/policydb.c | 5 ++++- 4 files changed, 35 insertions(+), 10 deletions(-)
include/linux/security.h +3 -0
@@ -61,6 +61,9 @@ struct mm_struct;#define SECURITY_CAP_NOAUDIT 0#define SECURITY_CAP_AUDIT 1 +/* LSM Agnostic defines for sb_set_mnt_opts */ +#define SECURITY_LSM_NATIVE_LABELS 1 +struct ctl_table ;struct audit_krule ;struct user_namespace ;
security/selinux/hooks.c +26 -9
@@ -80,6 +80,7 @@#include <linux/syslog.h> #include <linux/user_namespace.h> #include <linux/export.h> +#include <linux/security.h> #include <linux/msg.h> #include <linux/shm.h>
@@ -283,13 +284,14 @@ static void superblock_free_security(struct super_block *sb)/* The file system's label must be initialized prior to use. */ -static const char *labeling_behaviors[6 ] = { +static const char *labeling_behaviors[7 ] = {"uses xattr" ,"uses transition SIDs" ,"uses task SIDs" ,"uses genfs_contexts" ,"not configured for labeling" ,"uses mountpoint labeling" , +"uses native labeling" , };static int inode_doinit_with_dentry (struct inode *inode,struct dentry *opt_dentry);
@@ -677,14 +679,21 @@ static int selinux_set_mnt_opts(struct super_block *sb,if (strcmp (sb->s_type->name,"proc" ) ==0 ) sbsec->flags |=SE_SBPROC ; -/* Determine the labeling behavior to use for this filesystem type. */ - rc =security_fs_use ((sbsec->flags &SE_SBPROC ) ?"proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid); -if (rc) { -printk (KERN_WARNING "%s: security_fs_use(%s) returned %d\n" , - __func__, sb->s_type->name, rc); - goto out; +if (!sbsec->behavior) { +/* +* Determine the labeling behavior to use for this +* filesystem type. +*/ + rc =security_fs_use ((sbsec->flags &SE_SBPROC ) ? +"proc" : sb->s_type->name, + &sbsec->behavior, &sbsec->sid); +if (rc) { +printk (KERN_WARNING +"%s: security_fs_use(%s) returned %d\n" , + __func__, sb->s_type->name, rc); + goto out; + } } -/* sets the context of the superblock for the fs being mounted. */ if (fscontext_sid) { rc =may_context_mount_sb_relabel (fscontext_sid, sbsec, cred);
@@ -699,6 +708,11 @@ static int selinux_set_mnt_opts(struct super_block *sb,* sets the label used on all file below the mountpoint, and will set * the superblock context if not already set. */ +if (kern_flags &SECURITY_LSM_NATIVE_LABELS && !context_sid) { + sbsec->behavior =SECURITY_FS_USE_NATIVE ; + *set_kern_flags |=SECURITY_LSM_NATIVE_LABELS ; + } +if (context_sid) {if (!fscontext_sid) { rc = may_context_mount_sb_relabel(context_sid, sbsec,
@@ -730,7 +744,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, }if (defcontext_sid) { -if (sbsec->behavior !=SECURITY_FS_USE_XATTR ) { +if (sbsec->behavior !=SECURITY_FS_USE_XATTR && + sbsec->behavior !=SECURITY_FS_USE_NATIVE ) { rc = -EINVAL ;printk (KERN_WARNING "SELinux: defcontext option is " "invalid for this filesystem type\n" );
@@ -1198,6 +1213,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent }switch (sbsec->behavior) { +case SECURITY_FS_USE_NATIVE : +break ;case SECURITY_FS_USE_XATTR :if (!inode->i_op->getxattr) { isec->sid = sbsec->def_sid;
security/selinux/include/security.h +2 -0
@@ -169,6 +169,8 @@ int security_get_allow_unknown(void);#define SECURITY_FS_USE_GENFS 4/* use the genfs support */ #define SECURITY_FS_USE_NONE 5/* no labeling support */ #define SECURITY_FS_USE_MNTPOINT 6/* use mountpoint labeling */ +#define SECURITY_FS_USE_NATIVE 7/* use native label support */ +#define SECURITY_FS_USE_MAX 7/* Highest SECURITY_FS_USE_XXX */ int security_fs_use (const char *fstype,unsigned int *behavior,u32 *sid);
security/selinux/ss/policydb.c +4 -1
@@ -2168,7 +2168,10 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, rc = -EINVAL ; c->v.behavior =le32_to_cpu (buf[0 ]); -if (c->v.behavior >SECURITY_FS_USE_NONE ) +/* Determined at runtime, not in policy DB. */ +if (c->v.behavior ==SECURITY_FS_USE_MNTPOINT ) + goto out; +if (c->v.behavior >SECURITY_FS_USE_MAX ) goto out; rc = -ENOMEM ;
Signature · 1 line
1.7.11.7
PATCH 5/12 KConfig: Add KConfig entries for Labeled NFS
In reply to Steve DicksonFrom: David Quigley <[email protected]>
This patch adds two entries into the fs/KConfig file. The first entry NFS_V4_SECURITY_LABEL enables security label support for the NFSv4 client while the second entry NFSD_V4_SECURITY_LABEL enables security labeling support on the server side.
--- fs/nfs/Kconfig | 16 ++++++++++++++++ fs/nfsd/Kconfig | 13 +++++++++++++ 2 files changed, 29 insertions(+)
fs/nfs/Kconfig +16 -0
@@ -131,6 +131,22 @@ config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN If the NFS client is unchanged from the upstream kernel, this option should be set to the default "kernel.org". +config NFS_V4_SECURITY_LABEL + bool "Provide Security Label support for NFSv4 client" + depends on NFS_V4 && SECURITY + help + + Say Y here if you want enable fine-grained security label attribute + support for NFS version 4. Security labels allow security modules like + SELinux and Smack to label files to facilitate enforcement of their policies. + Without this an NFSv4 mount will have the same label on each file. + + If you do not wish to enable fine-grained security labels SELinux or + Smack policies on NFSv4 files, say N. + + + If unsure, say N. + config ROOT_NFS bool "Root file system on NFS" depends on NFS_FS=y && IP_PNP
fs/nfsd/Kconfig +13 -0
@@ -81,6 +81,19 @@ config NFSD_V4 If unsure, say N. +config NFSD_V4_SECURITY_LABEL + bool "Provide Security Label support for NFSv4 server" + depends on NFSD_V4 && SECURITY + help + + Say Y here if you want enable fine-grained security label attribute + support for NFS version 4. Security labels allow security modules like + SELinux and Smack to label files to facilitate enforcement of their policies. + Without this an NFSv4 mount will have the same label on each file. + + If you do not wish to enable fine-grained security labels SELinux or + Smack policies on NFSv4 files, say N. + config NFSD_FAULT_INJECTION bool "NFS server manual fault injection" depends on NFSD_V4 && DEBUG_KERNEL
Signature · 1 line
1.7.11.7
PATCH 6/12 NFSv4: Add label recommended attribute and NFSv4 flags
In reply to Steve DicksonFrom: David Quigley <[email protected]>
This patch adds several new flags to allow the NFS client to determine if this attribute is supported and if it is being sent over the wire.
--- include/linux/nfs4.h | 1 + include/linux/nfs_fs_sb.h | 1 + include/linux/nfs_xdr.h | 5 ++++- include/uapi/linux/nfs4.h | 1 + 4 files changed, 7 insertions(+), 1 deletion(-)
include/linux/nfs4.h +1 -0
@@ -373,6 +373,7 @@ enum lock_type4 {#define FATTR4_WORD1_MOUNTED_ON_FILEID (1UL << 23)#define FATTR4_WORD1_FS_LAYOUT_TYPES (1UL << 30)#define FATTR4_WORD2_LAYOUT_BLKSIZE (1UL << 1) +#define FATTR4_WORD2_SECURITY_LABEL (1UL << 17)#define FATTR4_WORD2_MDSTHRESHOLD (1UL << 4)/* MDS threshold bitmap bits */
include/linux/nfs_fs_sb.h +1 -0
@@ -197,5 +197,6 @@ struct nfs_server {#define NFS_CAP_MTIME (1U << 13)#define NFS_CAP_POSIX_LOCK (1U << 14)#define NFS_CAP_UIDGID_NOMAP (1U << 15) +#define NFS_CAP_SECURITY_LABEL (1U << 16)#endif
include/linux/nfs_xdr.h +4 -1
@@ -104,6 +104,7 @@ struct nfs_fattr {#define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 22)#define NFS_ATTR_FATTR_OWNER_NAME (1U << 23)#define NFS_ATTR_FATTR_GROUP_NAME (1U << 24) +#define NFS_ATTR_FATTR_V4_SECURITY_LABEL (1U << 25)#define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ | NFS_ATTR_FATTR_MODE \
@@ -123,7 +124,8 @@ struct nfs_fattr {#define NFS_ATTR_FATTR_V3 (NFS_ATTR_FATTR \ | NFS_ATTR_FATTR_SPACE_USED)#define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \ - | NFS_ATTR_FATTR_SPACE_USED) + | NFS_ATTR_FATTR_SPACE_USED \ + | NFS_ATTR_FATTR_V4_SECURITY_LABEL)/* * Info on the file system
@@ -597,6 +599,7 @@ struct nfs_entry {int eof;struct nfs_fh * fh;struct nfs_fattr * fattr; +struct nfs4_label *label;unsigned char d_type;struct nfs_server * server; };
include/uapi/linux/nfs4.h +1 -0
@@ -25,6 +25,7 @@#define NFS4_MAXNAMLEN NAME_MAX#define NFS4_OPAQUE_LIMIT 1024#define NFS4_MAX_SESSIONID_LEN 16 +#define NFS4_MAXLABELLEN 4096#define NFS4_ACCESS_READ 0x0001#define NFS4_ACCESS_LOOKUP 0x0002
Signature · 1 line
1.7.11.7
PATCH 7/12 NFSv4: Introduce new label structure
In reply to Steve DicksonFrom: David Quigley <[email protected]>
In order to mimic the way that NFSv4 ACLs are implemented we have created a structure to be used to pass label data up and down the call chain. This patch adds the new structure and new members to the required NFSv4 call structures.
--- fs/nfs/inode.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/linux/nfs4.h | 8 ++++++++ include/linux/nfs_fs.h | 14 ++++++++++++++ include/linux/nfs_xdr.h | 20 ++++++++++++++++++++ 4 files changed, 82 insertions(+)
fs/nfs/inode.c +40 -0
@@ -255,6 +255,46 @@ nfs_init_locked(struct inode *inode, void *opaque)return 0 ; } +#ifdef CONFIG_NFS_V4_SECURITY_LABEL +struct nfs4_label *nfs4_label_alloc (gfp_t flags) +{ +struct nfs4_label *label =NULL ; + + label =kzalloc (sizeof (struct nfs4_label ) +NFS4_MAXLABELLEN , flags); +if (label ==NULL ) +return NULL ; + + label->label = (void *)(label +1 ); + label->len =NFS4_MAXLABELLEN ; +/* 0 is the null format meaning that the data is not to be translated */ + label->lfs =0 ; + label->pi =0 ; +return label; +} +EXPORT_SYMBOL_GPL (nfs4_label_alloc); + +void nfs4_label_init (struct nfs4_label *label) +{ +if (label && label->label) { + *(unsigned char *)label->label =0 ; + label->len =NFS4_MAXLABELLEN ; +/* 0 is the null format meaning that the data is not +to be translated */ + label->lfs =0 ; + label->pi =0 ; + } +return ; +} +EXPORT_SYMBOL_GPL (nfs4_label_init); + +void nfs4_label_free (struct nfs4_label *label) +{ +kfree (label); +return ; +} +EXPORT_SYMBOL_GPL (nfs4_label_free); +#endif +/* * This is our front-end to iget that looks up inodes by file handle * instead of inode number.
include/linux/nfs4.h +8 -0
@@ -28,6 +28,14 @@ struct nfs4_acl {struct nfs4_ace aces[0 ]; }; +struct nfs4_label { +uint32_t lfs; +uint32_t pi; +u32 len; +void *label; +}; + +typedef struct {char data[NFS4_VERIFIER_SIZE ]; }nfs4_verifier ;struct nfs_stateid4 {
include/linux/nfs_fs.h +14 -0
@@ -489,6 +489,20 @@ extern int nfs_mountpoint_expiry_timeout;extern void nfs_release_automount_timer (void );/* +* linux/fs/nfs/nfs4proc.c +*/ + +#ifdef CONFIG_NFS_V4_SECURITY_LABEL +extern struct nfs4_label *nfs4_label_alloc (gfp_t flags); +extern void nfs4_label_init (struct nfs4_label *); +extern void nfs4_label_free (struct nfs4_label *); +#else +static inline struct nfs4_label *nfs4_label_alloc (gfp_t flags) {return NULL ; } +static inline void nfs4_label_init (void *label) {} +static inline void nfs4_label_free (void *label) {} +#endif + +/* * linux/fs/nfs/unlink.c */ extern void nfs_complete_unlink (struct dentry *dentry,struct inode *);
include/linux/nfs_xdr.h +20 -0
@@ -350,6 +350,7 @@ struct nfs_openargs {const u32 * bitmask;const u32 * open_bitmap;__u32 claim; +const struct nfs4_label *label; };struct nfs_openres {
@@ -359,6 +360,7 @@ struct nfs_openres {struct nfs4_change_info cinfo;__u32 rflags;struct nfs_fattr * f_attr; +struct nfs4_label *f_label;struct nfs_seqid * seqid;const struct nfs_server *server;fmode_t delegation_type;
@@ -403,6 +405,7 @@ struct nfs_closeres {struct nfs4_sequence_res seq_res;nfs4_stateid stateid;struct nfs_fattr * fattr; +struct nfs4_label *label;struct nfs_seqid * seqid;const struct nfs_server *server; };
@@ -476,6 +479,7 @@ struct nfs4_delegreturnargs {struct nfs4_delegreturnres {struct nfs4_sequence_res seq_res;struct nfs_fattr * fattr; +struct nfs4_label *label;const struct nfs_server *server; };
@@ -496,6 +500,7 @@ struct nfs_readargs {struct nfs_readres {struct nfs4_sequence_res seq_res;struct nfs_fattr * fattr; +struct nfs4_label *label;__u32 count;int eof; };
@@ -564,6 +569,7 @@ struct nfs_removeres {struct nfs4_sequence_res seq_res;const struct nfs_server *server;struct nfs_fattr *dir_attr; +struct nfs4_label *dir_label;struct nfs4_change_info cinfo; };
@@ -576,6 +582,8 @@ struct nfs_renameargs {const struct nfs_fh *new_dir;const struct qstr *old_name;const struct qstr *new_name; +const struct nfs4_label *old_label; +const struct nfs4_label *new_label; };struct nfs_renameres {
@@ -583,8 +591,10 @@ struct nfs_renameres {const struct nfs_server *server;struct nfs4_change_info old_cinfo;struct nfs_fattr *old_fattr; +struct nfs4_label *old_label;struct nfs4_change_info new_cinfo;struct nfs_fattr *new_fattr; +struct nfs4_label *new_label; };/*
@@ -632,6 +642,7 @@ struct nfs_setattrargs {struct iattr * iap;const struct nfs_server * server;/* Needed for name mapping */ const u32 * bitmask; +const struct nfs4_label *label; };struct nfs_setaclargs {
@@ -667,6 +678,7 @@ struct nfs_getaclres {struct nfs_setattrres {struct nfs4_sequence_res seq_res;struct nfs_fattr * fattr; +struct nfs4_label *label;const struct nfs_server * server; };
@@ -712,6 +724,7 @@ struct nfs3_setaclargs {struct nfs_diropok {struct nfs_fh * fh;struct nfs_fattr * fattr; +struct nfs4_label *label; };struct nfs_readlinkargs {
@@ -842,6 +855,7 @@ struct nfs4_accessres {struct nfs4_sequence_res seq_res;const struct nfs_server * server;struct nfs_fattr * fattr; +struct nfs4_label *label;u32 supported;u32 access; };
@@ -864,6 +878,7 @@ struct nfs4_create_arg {const struct iattr * attrs;const struct nfs_fh * dir_fh;const u32 * bitmask; +const struct nfs4_label *label; };struct nfs4_create_res {
@@ -871,6 +886,7 @@ struct nfs4_create_res {const struct nfs_server * server;struct nfs_fh * fh;struct nfs_fattr * fattr; +struct nfs4_label *label;struct nfs4_change_info dir_cinfo; };
@@ -895,6 +911,7 @@ struct nfs4_getattr_res {struct nfs4_sequence_res seq_res;const struct nfs_server * server;struct nfs_fattr * fattr; +struct nfs4_label *label; };struct nfs4_link_arg {
@@ -909,8 +926,10 @@ struct nfs4_link_res {struct nfs4_sequence_res seq_res;const struct nfs_server * server;struct nfs_fattr * fattr; +struct nfs4_label *label;struct nfs4_change_info cinfo;struct nfs_fattr * dir_attr; +struct nfs4_label *dir_label; };
@@ -926,6 +945,7 @@ struct nfs4_lookup_res {const struct nfs_server * server;struct nfs_fattr * fattr;struct nfs_fh * fh; +struct nfs4_label *label; };struct nfs4_lookup_root_arg {
Signature · 1 line
1.7.11.7
PATCH 8/12 NFSv4: Extend fattr bitmaps to support all 3 words
In reply to Steve DicksonFrom: David Quigley <[email protected]>
The fattr handling bitmap code only uses the first two fattr words sofar. This patch adds the 3rd word to being sent but doesn't populate it yet.
--- fs/nfs/nfs4_fs.h | 6 +++--- fs/nfs/nfs4proc.c | 20 +++++++++++++------- fs/nfs/nfs4xdr.c | 20 ++++++++++++-------- fs/nfs/super.c | 1 + include/linux/nfs_fs_sb.h | 2 +- 5 files changed, 30 insertions(+), 19 deletions(-)
fs/nfs/nfs4_fs.h +3 -3
@@ -291,10 +291,10 @@ is_ds_client(struct nfs_client *clp)extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[];extern const u32 nfs4_fattr_bitmap[3 ]; -extern const u32 nfs4_statfs_bitmap[2 ]; -extern const u32 nfs4_pathconf_bitmap[2 ]; +extern const u32 nfs4_statfs_bitmap[3 ]; +extern const u32 nfs4_pathconf_bitmap[3 ];extern const u32 nfs4_fsinfo_bitmap[3 ]; -extern const u32 nfs4_fs_locations_bitmap[2 ]; +extern const u32 nfs4_fs_locations_bitmap[3 ];void nfs4_free_client (struct nfs_client *);
fs/nfs/nfs4proc.c +13 -7
@@ -130,7 +130,8 @@ const u32 nfs4_fattr_bitmap[3] = { | FATTR4_WORD1_SPACE_USED | FATTR4_WORD1_TIME_ACCESS | FATTR4_WORD1_TIME_METADATA - | FATTR4_WORD1_TIME_MODIFY + | FATTR4_WORD1_TIME_MODIFY, + 0 };static const u32 nfs4_pnfs_open_bitmap[3 ] = {
@@ -157,18 +158,20 @@ static const u32 nfs4_open_noattr_bitmap[3] = { | FATTR4_WORD0_FILEID, }; -const u32 nfs4_statfs_bitmap[2 ] = { +const u32 nfs4_statfs_bitmap[3 ] = {FATTR4_WORD0_FILES_AVAIL |FATTR4_WORD0_FILES_FREE |FATTR4_WORD0_FILES_TOTAL ,FATTR4_WORD1_SPACE_AVAIL |FATTR4_WORD1_SPACE_FREE - |FATTR4_WORD1_SPACE_TOTAL + |FATTR4_WORD1_SPACE_TOTAL , +0 }; -const u32 nfs4_pathconf_bitmap[2 ] = { +const u32 nfs4_pathconf_bitmap[3 ] = {FATTR4_WORD0_MAXLINK |FATTR4_WORD0_MAXNAME , +0 ,0 };
@@ -181,7 +184,7 @@ const u32 nfs4_fsinfo_bitmap[3] = { FATTR4_WORD0_MAXFILESIZEFATTR4_WORD2_LAYOUT_BLKSIZE }; -const u32 nfs4_fs_locations_bitmap[2 ] = { +const u32 nfs4_fs_locations_bitmap[3 ] = {FATTR4_WORD0_TYPE |FATTR4_WORD0_CHANGE |FATTR4_WORD0_SIZE
@@ -197,7 +200,8 @@ const u32 nfs4_fs_locations_bitmap[2] = { | FATTR4_WORD1_TIME_ACCESS | FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY - | FATTR4_WORD1_MOUNTED_ON_FILEID + | FATTR4_WORD1_MOUNTED_ON_FILEID, + 0 }; static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
@@ -5078,8 +5082,10 @@ static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, struct page *page) {struct nfs_server *server =NFS_SERVER (dir); -u32 bitmask[2 ] = { +u32 bitmask[3 ] = { [0 ] =FATTR4_WORD0_FSID |FATTR4_WORD0_FS_LOCATIONS , + [1 ] =0 , + [2 ] =0 };struct nfs4_fs_locations_arg args = { .dir_fh =NFS_FH (dir),
fs/nfs/nfs4xdr.c +12 -8
@@ -983,15 +983,16 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, constint len;uint32_t bmval0 =0 ;uint32_t bmval1 =0 ; +uint32_t bmval2 =0 ;/* * We reserve enough space to write the entire attribute buffer at once. * In the worst-case, this would be -* 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) -* = 36 bytes, plus any contribution from variable-length fields +* 16(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) +* = 40 bytes, plus any contribution from variable-length fields * such as owner/group. */ - len =16 ; + len =20 ;/* Sigh */ if (iap->ia_valid &ATTR_SIZE )
@@ -1035,9 +1036,9 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const* We write the bitmap length now, but leave the bitmap and the attribute * buffer length to be backfilled at the end of this routine. */ - *p++ =cpu_to_be32 (2 ); + *p++ =cpu_to_be32 (3 ); q = p; - p +=3 ; + p +=4 ;if (iap->ia_valid &ATTR_SIZE ) { bmval0 |=FATTR4_WORD0_SIZE ;
@@ -1086,9 +1087,10 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const len, ((char *)p - (char *)q) + 4);BUG (); } - len = (char *)p - (char *)q -12 ; + len = (char *)p - (char *)q -16 ; *q++ =htonl (bmval0); *q++ =htonl (bmval1); + *q++ =htonl (bmval2); *q =htonl (len);/* out: */
@@ -1194,8 +1196,10 @@ encode_getattr_three(struct xdr_stream *xdr,static void encode_getfattr (struct xdr_stream *xdr,const u32 * bitmask,struct compound_hdr *hdr) { -encode_getattr_two (xdr, bitmask[0 ] & nfs4_fattr_bitmap[0 ], - bitmask[1 ] & nfs4_fattr_bitmap[1 ], hdr); +encode_getattr_three (xdr, bitmask[0 ] & nfs4_fattr_bitmap[0 ], + bitmask[1 ] & nfs4_fattr_bitmap[1 ], + bitmask[2 ] & nfs4_fattr_bitmap[2 ], + hdr); } static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask,
fs/nfs/super.c +1 -0
@@ -877,6 +877,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root)seq_printf (m,"\n\tnfsv4:\t" );seq_printf (m,"bm0=0x%x" , nfss->attr_bitmask[0 ]);seq_printf (m,",bm1=0x%x" , nfss->attr_bitmask[1 ]); +seq_printf (m,",bm2=0x%x" , nfss->attr_bitmask[2 ]);seq_printf (m,",acl=0x%x" , nfss->acl_bitmask);show_sessions (m, nfss);show_pnfs (m, nfss);
include/linux/nfs_fs_sb.h +1 -1
@@ -145,7 +145,7 @@ struct nfs_server {u32 attr_bitmask[3 ];/* V4 bitmask representing the set of attributes supported on this filesystem */ -u32 cache_consistency_bitmask[2 ]; +u32 cache_consistency_bitmask[3 ];/* V4 bitmask representing the subset of change attribute, size, ctime and mtime attributes supported by
Signature · 1 line
1.7.11.7
PATCH 9/12 NFS:Add labels to client function prototypes
In reply to Steve DicksonFrom: Dave Quigley <[email protected]>
Quoted 1 line
From David Quigley <[email protected]>
After looking at all of the nfsv4 operations the label structure has been added to the prototypes of the functions which can transmit label data.
--- fs/nfs/client.c | 2 +- fs/nfs/dir.c | 23 +++++----- fs/nfs/getroot.c | 3 +- fs/nfs/inode.c | 33 +++++++------- fs/nfs/namespace.c | 2 +- fs/nfs/nfs3acl.c | 4 +- fs/nfs/nfs3proc.c | 41 ++++++++--------- fs/nfs/nfs4_fs.h | 2 +- fs/nfs/nfs4namespace.c | 2 +- fs/nfs/nfs4proc.c | 117 +++++++++++++++++++++++++++++++----------------- fs/nfs/proc.c | 15 ++++--- include/linux/nfs_fs.h | 9 ++-- include/linux/nfs_xdr.h | 5 ++- 13 files changed, 150 insertions(+), 108 deletions(-)
fs/nfs/client.c +1 -1
@@ -1075,7 +1075,7 @@ struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info, }if (!(fattr->valid &NFS_ATTR_FATTR )) { - error = nfs_mod->rpc_ops->getattr (server, mount_info->mntfh, fattr); + error = nfs_mod->rpc_ops->getattr (server, mount_info->mntfh, fattr,NULL );if (error <0 ) {dprintk ("nfs_create_server: getattr error = %d\n" , -error); goto error;
fs/nfs/dir.c +13 -10
@@ -447,7 +447,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) dentry =d_lookup (parent, &filename);if (dentry !=NULL ) {if (nfs_same_file (dentry, entry)) { -nfs_refresh_inode (dentry->d_inode, entry->fattr); +nfs_refresh_inode (dentry->d_inode, entry->fattr, entry->label); goto out; }else {if (d_invalidate (dentry) !=0 )
@@ -460,7 +460,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)if (dentry ==NULL )return ; - inode =nfs_fhget (dentry->d_sb, entry->fh, entry->fattr); + inode =nfs_fhget (dentry->d_sb, entry->fh, entry->fattr, entry->label);if (IS_ERR (inode)) goto out;
@@ -1040,6 +1040,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)struct dentry *parent;struct nfs_fh *fhandle =NULL ;struct nfs_fattr *fattr =NULL ; +struct nfs4_label *label =NULL ;int error;if (flags &LOOKUP_RCU )
@@ -1082,12 +1083,12 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)if (fhandle ==NULL || fattr ==NULL ) goto out_error; - error =NFS_PROTO (dir)->lookup (dir, &dentry->d_name, fhandle, fattr); + error =NFS_PROTO (dir)->lookup (dir, &dentry->d_name, fhandle, fattr, label);if (error) goto out_bad;if (nfs_compare_fh (NFS_FH (inode), fhandle)) goto out_bad; -if ((error =nfs_refresh_inode (inode, fattr)) !=0 ) +if ((error =nfs_refresh_inode (inode, fattr, label)) !=0 ) goto out_bad;nfs_free_fattr (fattr);
@@ -1216,6 +1217,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned instruct inode *inode =NULL ;struct nfs_fh *fhandle =NULL ;struct nfs_fattr *fattr =NULL ; +struct nfs4_label *label =NULL ;int error; dfprintk(VFS, "NFS: lookup(%s/%s)\n",
@@ -1245,14 +1247,14 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in parent = dentry->d_parent;/* Protect against concurrent sillydeletes */ nfs_block_sillyrename (parent); - error =NFS_PROTO (dir)->lookup (dir, &dentry->d_name, fhandle, fattr); + error =NFS_PROTO (dir)->lookup (dir, &dentry->d_name, fhandle, fattr, label);if (error == -ENOENT ) goto no_entry;if (error <0 ) { res =ERR_PTR (error); goto out_unblock_sillyrename; } - inode =nfs_fhget (dentry->d_sb, fhandle, fattr); + inode =nfs_fhget (dentry->d_sb, fhandle, fattr, label); res =ERR_CAST (inode);if (IS_ERR (res)) goto out_unblock_sillyrename;
@@ -1486,7 +1488,8 @@ no_open:* Code common to create, mkdir, and mknod. */ int nfs_instantiate (struct dentry *dentry,struct nfs_fh *fhandle, -struct nfs_fattr *fattr) +struct nfs_fattr *fattr, +struct nfs4_label *label) {struct dentry *parent =dget_parent (dentry);struct inode *dir = parent->d_inode;
@@ -1499,18 +1502,18 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,if (dentry->d_inode) goto out;if (fhandle->size ==0 ) { - error =NFS_PROTO (dir)->lookup (dir, &dentry->d_name, fhandle, fattr); + error =NFS_PROTO (dir)->lookup (dir, &dentry->d_name, fhandle, fattr,NULL );if (error) goto out_error; }nfs_set_verifier (dentry,nfs_save_change_attribute (dir));if (!(fattr->valid &NFS_ATTR_FATTR )) {struct nfs_server *server =NFS_SB (dentry->d_sb); - error = server->nfs_client->rpc_ops->getattr (server, fhandle, fattr); + error = server->nfs_client->rpc_ops->getattr (server, fhandle, fattr,NULL );if (error <0 ) goto out_error; } - inode =nfs_fhget (dentry->d_sb, fhandle, fattr); + inode =nfs_fhget (dentry->d_sb, fhandle, fattr, label); error =PTR_ERR (inode);if (IS_ERR (inode)) goto out_error;
fs/nfs/getroot.c +2 -1
@@ -75,6 +75,7 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh,struct nfs_fsinfo fsinfo;struct dentry *ret;struct inode *inode; +struct nfs4_label *label =NULL ;void *name =kstrdup (devname,GFP_KERNEL );int error;
@@ -95,7 +96,7 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh, goto out; } - inode =nfs_fhget (sb, mntfh, fsinfo.fattr); + inode =nfs_fhget (sb, mntfh, fsinfo.fattr, label);if (IS_ERR (inode)) {dprintk ("nfs_get_root: get root inode failed\n" ); ret =ERR_CAST (inode);
fs/nfs/inode.c +17 -16
@@ -61,7 +61,7 @@static bool enable_ino64 =NFS_64_BIT_INODE_NUMBERS_ENABLED ;static void nfs_invalidate_inode (struct inode *); -static int nfs_update_inode (struct inode *,struct nfs_fattr *); +static int nfs_update_inode (struct inode *,struct nfs_fattr *,struct nfs4_label *);static struct kmem_cache * nfs_inode_cachep;
@@ -300,7 +300,7 @@ EXPORT_SYMBOL_GPL(nfs4_label_free);* instead of inode number. */ struct inode * -nfs_fhget (struct super_block *sb,struct nfs_fh *fh,struct nfs_fattr *fattr) +nfs_fhget (struct super_block *sb,struct nfs_fh *fh,struct nfs_fattr *fattr,struct nfs4_label *label) {struct nfs_find_desc desc = { .fh = fh,
@@ -430,7 +430,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)unlock_new_inode (inode); }else -nfs_refresh_inode (inode, fattr); +nfs_refresh_inode (inode, fattr, label); dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n", inode->i_sb->s_id, (long long)NFS_FILEID(inode),
@@ -487,7 +487,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)NFS_PROTO (inode)->return_delegation (inode); error =NFS_PROTO (inode)->setattr (dentry, fattr, attr);if (error ==0 ) -nfs_refresh_inode (inode, fattr); +nfs_refresh_inode (inode, fattr,NULL );nfs_free_fattr (fattr); out:return error;
@@ -829,6 +829,7 @@ int __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) { int status = -ESTALE; +struct nfs4_label *label =NULL ;struct nfs_fattr *fattr =NULL ;struct nfs_inode *nfsi =NFS_I (inode);
@@ -846,7 +847,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) goto out;nfs_inc_stats (inode,NFSIOS_INODEREVALIDATE ); - status =NFS_PROTO (inode)->getattr (server,NFS_FH (inode), fattr); + status =NFS_PROTO (inode)->getattr (server,NFS_FH (inode), fattr, label);if (status !=0 ) { dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", inode->i_sb->s_id,
@@ -859,7 +860,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) goto out; } - status =nfs_refresh_inode (inode, fattr); + status =nfs_refresh_inode (inode, fattr, label);if (status) { dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", inode->i_sb->s_id,
@@ -1216,10 +1217,10 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n ((long )nfsi->attr_gencount - (long )nfs_read_attr_generation_counter () >0 ); } -static int nfs_refresh_inode_locked (struct inode *inode,struct nfs_fattr *fattr) +static int nfs_refresh_inode_locked (struct inode *inode,struct nfs_fattr *fattr,struct nfs4_label *label) {if (nfs_inode_attrs_need_update (inode, fattr)) -return nfs_update_inode (inode, fattr); +return nfs_update_inode (inode, fattr, label);return nfs_check_inode_attributes (inode, fattr); }
@@ -1233,21 +1234,21 @@ static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr* safe to do a full update of the inode attributes, or whether just to * call nfs_check_inode_attributes. */ -int nfs_refresh_inode (struct inode *inode,struct nfs_fattr *fattr) +int nfs_refresh_inode (struct inode *inode,struct nfs_fattr *fattr,struct nfs4_label *label) {int status;if ((fattr->valid &NFS_ATTR_FATTR ) ==0 )return 0 ;spin_lock (&inode->i_lock); - status =nfs_refresh_inode_locked (inode, fattr); + status =nfs_refresh_inode_locked (inode, fattr, label);spin_unlock (&inode->i_lock);return status; }EXPORT_SYMBOL_GPL (nfs_refresh_inode); -static int nfs_post_op_update_inode_locked (struct inode *inode,struct nfs_fattr *fattr) +static int nfs_post_op_update_inode_locked (struct inode *inode,struct nfs_fattr *fattr,struct nfs4_label *label) {struct nfs_inode *nfsi =NFS_I (inode);
@@ -1258,7 +1259,7 @@ static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr }if ((fattr->valid &NFS_ATTR_FATTR ) ==0 )return 0 ; -return nfs_refresh_inode_locked (inode, fattr); +return nfs_refresh_inode_locked (inode, fattr, label); }/**
@@ -1275,12 +1276,12 @@ static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr* are expected to change one or more attributes, to avoid * unnecessary NFS requests and trips through nfs_update_inode(). */ -int nfs_post_op_update_inode (struct inode *inode,struct nfs_fattr *fattr) +int nfs_post_op_update_inode (struct inode *inode,struct nfs_fattr *fattr,struct nfs4_label *label) {int status;spin_lock (&inode->i_lock); - status =nfs_post_op_update_inode_locked (inode, fattr); + status =nfs_post_op_update_inode_locked (inode, fattr, label);spin_unlock (&inode->i_lock);return status; }
@@ -1332,7 +1333,7 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa fattr->valid |=NFS_ATTR_FATTR_PRESIZE ; } out_noforce: - status =nfs_post_op_update_inode_locked (inode, fattr); + status =nfs_post_op_update_inode_locked (inode, fattr,NULL );spin_unlock (&inode->i_lock);return status; }
@@ -1350,7 +1351,7 @@ EXPORT_SYMBOL_GPL(nfs_post_op_update_inode_force_wcc);* * A very similar scenario holds for the dir cache. */ -static int nfs_update_inode (struct inode *inode,struct nfs_fattr *fattr) +static int nfs_update_inode (struct inode *inode,struct nfs_fattr *fattr,struct nfs4_label *label) {struct nfs_server *server;struct nfs_inode *nfsi =NFS_I (inode);
fs/nfs/namespace.c +1 -1
@@ -260,7 +260,7 @@ struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry,struct dentry *parent =dget_parent (dentry);/* Look it up again to get its attributes */ - err = server->nfs_client->rpc_ops->lookup (parent->d_inode, &dentry->d_name, fh, fattr); + err = server->nfs_client->rpc_ops->lookup (parent->d_inode, &dentry->d_name, fh, fattr,NULL );dput (parent);if (err !=0 )return ERR_PTR (err);
fs/nfs/nfs3acl.c +2 -2
@@ -240,7 +240,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)switch (status) {case 0 : - status =nfs_refresh_inode (inode, res.fattr); + status =nfs_refresh_inode (inode, res.fattr,NULL );break ;case -EPFNOSUPPORT :case -EPROTONOSUPPORT :
@@ -352,7 +352,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,switch (status) {case 0 : - status =nfs_refresh_inode (inode, fattr); + status =nfs_refresh_inode (inode, fattr,NULL );nfs3_cache_acls (inode, acl, dfacl);break ;case -EPFNOSUPPORT :
fs/nfs/nfs3proc.c +21 -20
138 lines not on this page · raw message
fs/nfs/nfs4_fs.h +1 -1
@@ -225,7 +225,7 @@ extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhextern int nfs4_proc_fs_locations (struct rpc_clnt *,struct inode *,const struct qstr *,struct nfs4_fs_locations *,struct page *);extern struct rpc_clnt *nfs4_proc_lookup_mountpoint (struct inode *,struct qstr *, -struct nfs_fh *,struct nfs_fattr *); +struct nfs_fh *,struct nfs_fattr *,struct nfs4_label *);extern int nfs4_proc_secinfo (struct inode *,const struct qstr *,struct nfs4_secinfo_flavors *);extern int nfs4_release_lockowner (struct nfs4_lock_state *);extern const struct xattr_handler *nfs4_xattr_handlers[];
fs/nfs/nfs4namespace.c +1 -1
@@ -368,7 +368,7 @@ struct vfsmount *nfs4_submount(struct nfs_server *server, struct dentry *dentry,struct vfsmount *mnt;/* Look it up again to get its attributes and sec flavor */ - client =nfs4_proc_lookup_mountpoint (parent->d_inode, &dentry->d_name, fh, fattr); + client =nfs4_proc_lookup_mountpoint (parent->d_inode, &dentry->d_name, fh, fattr,NULL );dput (parent);if (IS_ERR (client))return ERR_CAST (client);
fs/nfs/nfs4proc.c +75 -42
463 lines not on this page · raw message
fs/nfs/proc.c +8 -7
@@ -98,7 +98,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,*/ static int nfs_proc_getattr (struct nfs_server *server,struct nfs_fh *fhandle, -struct nfs_fattr *fattr) +struct nfs_fattr *fattr,struct nfs4_label *label) {struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_GETATTR ],
@@ -146,7 +146,8 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,static int nfs_proc_lookup (struct inode *dir,struct qstr *name, -struct nfs_fh *fhandle,struct nfs_fattr *fattr) +struct nfs_fh *fhandle,struct nfs_fattr *fattr, +struct nfs4_label *label) {struct nfs_diropargs arg = { .fh =NFS_FH (dir),
@@ -243,7 +244,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, status =rpc_call_sync (NFS_CLIENT (dir), &msg,0 );nfs_mark_for_revalidate (dir);if (status ==0 ) - status =nfs_instantiate (dentry, data->res.fh, data->res.fattr); + status =nfs_instantiate (dentry, data->res.fh, data->res.fattr,NULL );nfs_free_createdata (data); out:dprintk ("NFS reply create: %d\n" , status);
@@ -290,7 +291,7 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, status =rpc_call_sync (NFS_CLIENT (dir), &msg,0 ); }if (status ==0 ) - status =nfs_instantiate (dentry, data->res.fh, data->res.fattr); + status =nfs_instantiate (dentry, data->res.fh, data->res.fattr,NULL );nfs_free_createdata (data); out:dprintk ("NFS reply mknod: %d\n" , status);
@@ -442,7 +443,7 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,* should fill in the data with a LOOKUP call on the wire. */ if (status ==0 ) - status =nfs_instantiate (dentry, fh, fattr); + status =nfs_instantiate (dentry, fh, fattr,NULL ); out_free:nfs_free_fattr (fattr);
@@ -471,7 +472,7 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) status =rpc_call_sync (NFS_CLIENT (dir), &msg,0 );nfs_mark_for_revalidate (dir);if (status ==0 ) - status =nfs_instantiate (dentry, data->res.fh, data->res.fattr); + status =nfs_instantiate (dentry, data->res.fh, data->res.fattr,NULL );nfs_free_createdata (data); out:dprintk ("NFS reply mkdir: %d\n" , status);
@@ -607,7 +608,7 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)nfs_invalidate_atime (inode);if (task->tk_status >=0 ) { -nfs_refresh_inode (inode, data->res.fattr); +nfs_refresh_inode (inode, data->res.fattr, data->res.label);/* Emulate the eof flag, which isn't normally needed in NFSv2 * as it is guaranteed to always return the file attributes */
include/linux/nfs_fs.h +5 -4
@@ -328,9 +328,9 @@ extern void nfs_zap_mapping(struct inode *inode, struct address_space *mapping);extern void nfs_zap_caches (struct inode *);extern void nfs_invalidate_atime (struct inode *);extern struct inode *nfs_fhget (struct super_block *,struct nfs_fh *, -struct nfs_fattr *); -extern int nfs_refresh_inode (struct inode *,struct nfs_fattr *); -extern int nfs_post_op_update_inode (struct inode *inode,struct nfs_fattr *fattr); +struct nfs_fattr *,struct nfs4_label *); +extern int nfs_refresh_inode (struct inode *,struct nfs_fattr *,struct nfs4_label *); +extern int nfs_post_op_update_inode (struct inode *inode,struct nfs_fattr *fattr,struct nfs4_label *);extern int nfs_post_op_update_inode_force_wcc (struct inode *inode,struct nfs_fattr *fattr);extern int nfs_getattr (struct vfsmount *,struct dentry *,struct kstat *);extern void nfs_access_add_cache (struct inode *,struct nfs_access_entry *);
@@ -460,7 +460,8 @@ extern const struct file_operations nfs_dir_operations;extern const struct dentry_operations nfs_dentry_operations;extern void nfs_force_lookup_revalidate (struct inode *dir); -extern int nfs_instantiate (struct dentry *dentry,struct nfs_fh *fh,struct nfs_fattr *fattr); +extern int nfs_instantiate (struct dentry *dentry,struct nfs_fh *fh, +struct nfs_fattr *fattr,struct nfs4_label *label);extern int nfs_may_open (struct inode *inode,struct rpc_cred *cred,int openflags);extern void nfs_access_zap_cache (struct inode *inode);
include/linux/nfs_xdr.h +3 -2
@@ -1399,11 +1399,12 @@ struct nfs_rpc_ops {struct dentry *(*try_mount) (int ,const char *,struct nfs_mount_info *,struct nfs_subversion *);int (*getattr) (struct nfs_server *,struct nfs_fh *, -struct nfs_fattr *); +struct nfs_fattr *,struct nfs4_label *);int (*setattr) (struct dentry *,struct nfs_fattr *,struct iattr *);int (*lookup) (struct inode *,struct qstr *, -struct nfs_fh *,struct nfs_fattr *); +struct nfs_fh *,struct nfs_fattr *, +struct nfs4_label *);int (*access) (struct inode *,struct nfs_access_entry *);int (*readlink)(struct inode *,struct page *,unsigned int ,unsigned int );
Signature · 1 line
1.7.11.7
PATCH 10/12 NFS: Add label lifecycle management
In reply to Steve DicksonFrom: Dave Quigley <[email protected]>
Quoted 1 line
From David Quigley <[email protected]>
This patch adds the lifecycle management for the security label structure introduced in an earlier patch. The label is not used yet but allocations and freeing of the structure is handled.
--- fs/nfs/dir.c | 30 ++++++++++++++ fs/nfs/getroot.c | 3 +- fs/nfs/inode.c | 15 ++++++- fs/nfs/nfs4proc.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++-- include/linux/nfs_fs.h | 4 +- 5 files changed, 150 insertions(+), 7 deletions(-)
fs/nfs/dir.c +30 -0
@@ -585,6 +585,12 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,if (entry.fh ==NULL || entry.fattr ==NULL ) goto out; + entry.label =nfs4_label_alloc (GFP_NOWAIT ); +if (NFS4_LABEL_ERR (entry.label)) { + status =PTR_ERR (entry.label); + goto out; + } + array =nfs_readdir_get_array (page);if (IS_ERR (array)) { status =PTR_ERR (array);
@@ -617,6 +623,7 @@ out_release_array: out:nfs_free_fattr (entry.fattr);nfs_free_fhandle (entry.fh); +nfs4_label_free (entry.label);return status; }
@@ -1083,6 +1090,12 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)if (fhandle ==NULL || fattr ==NULL ) goto out_error; +if (nfs_server_capable (dir,NFS_CAP_SECURITY_LABEL )) { + label =nfs4_label_alloc (GFP_NOWAIT ); +if (NFS4_LABEL_ERR (label)) + goto out_error; + } + error =NFS_PROTO (dir)->lookup (dir, &dentry->d_name, fhandle, fattr, label);if (error) goto out_bad;
@@ -1093,6 +1106,12 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)nfs_free_fattr (fattr);nfs_free_fhandle (fhandle); + +#ifdef CONFIG_NFS_V4_SECURITY_LABEL +if (nfs_server_capable (dir,NFS_CAP_SECURITY_LABEL )) +nfs4_label_free (label); +#endif + out_set_verifier:nfs_set_verifier (dentry,nfs_save_change_attribute (dir)); out_valid:
@@ -1129,6 +1148,7 @@ out_zap_parent: out_error:nfs_free_fattr (fattr);nfs_free_fhandle (fhandle); +nfs4_label_free (label);dput (parent); dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", __func__, dentry->d_parent->d_name.name,
@@ -1244,6 +1264,12 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned inif (fhandle ==NULL || fattr ==NULL ) goto out; +if (nfs_server_capable (dir,NFS_CAP_SECURITY_LABEL )) { + label =nfs4_label_alloc (GFP_NOWAIT ); +if (NFS4_LABEL_ERR (label)) + goto out; + } + parent = dentry->d_parent;/* Protect against concurrent sillydeletes */ nfs_block_sillyrename (parent);
@@ -1273,6 +1299,10 @@ no_entry: out_unblock_sillyrename:nfs_unblock_sillyrename (parent); out: +#ifdef CONFIG_NFS_V4_SECURITY_LABEL +if (nfs_server_capable (dir,NFS_CAP_SECURITY_LABEL )) +nfs4_label_free (label); +#endif nfs_free_fattr (fattr);nfs_free_fhandle (fhandle);return res;
fs/nfs/getroot.c +1 -2
@@ -75,7 +75,6 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh,struct nfs_fsinfo fsinfo;struct dentry *ret;struct inode *inode; -struct nfs4_label *label =NULL ;void *name =kstrdup (devname,GFP_KERNEL );int error;
@@ -96,7 +95,7 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh, goto out; } - inode =nfs_fhget (sb, mntfh, fsinfo.fattr, label); + inode =nfs_fhget (sb, mntfh, fsinfo.fattr,NULL );if (IS_ERR (inode)) {dprintk ("nfs_get_root: get root inode failed\n" ); ret =ERR_CAST (inode);
fs/nfs/inode.c +14 -1
@@ -262,7 +262,7 @@ struct nfs4_label *nfs4_label_alloc(gfp_t flags) label =kzalloc (sizeof (struct nfs4_label ) +NFS4_MAXLABELLEN , flags);if (label ==NULL ) -return NULL ; +return ERR_PTR (-ENOMEM ); label->label = (void *)(label +1 ); label->len =NFS4_MAXLABELLEN ;
@@ -847,6 +847,15 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) goto out;nfs_inc_stats (inode,NFSIOS_INODEREVALIDATE ); + +if (nfs_server_capable (inode,NFS_CAP_SECURITY_LABEL )) { + label =nfs4_label_alloc (GFP_KERNEL ); +if (NFS4_LABEL_ERR (label)) { + status = -ENOMEM ; + goto out; + } + } + status =NFS_PROTO (inode)->getattr (server,NFS_FH (inode), fattr, label);if (status !=0 ) { dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
@@ -876,6 +885,10 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) (long long)NFS_FILEID(inode)); out: +#ifdef CONFIG_NFS_V4_SECURITY_LABEL +if (nfs_server_capable (inode,NFS_CAP_SECURITY_LABEL )) +nfs4_label_free (label); +#endif nfs_free_fattr (fattr);return status; }
fs/nfs/nfs4proc.c +102 -3
230 lines not on this page · raw message
include/linux/nfs_fs.h +3 -1
@@ -498,10 +498,12 @@ extern struct nfs4_label *nfs4_label_alloc(gfp_t flags);extern void nfs4_label_init (struct nfs4_label *);extern void nfs4_label_free (struct nfs4_label *);#else -static inline struct nfs4_label *nfs4_label_alloc (gfp_t flags) {return NULL ; } +static inline struct nfs4_label *nfs4_label_alloc (gfp_t flags) {return ERR_PTR (ENOTSUPP ); }static inline void nfs4_label_init (void *label) {}static inline void nfs4_label_free (void *label) {}#endif +#define NFS4_LABEL_ERR (_label) \ + (IS_ERR(_label) && PTR_ERR(_label) != -ENOTSUPP)/* * linux/fs/nfs/unlink.c
Signature · 1 line
1.7.11.7
PATCH 11/12 NFS: Client implementation of Labeled-NFS
In reply to Steve DicksonFrom: David Quigley <[email protected]>
This patch implements the client transport and handling support for labeled NFS. The patch adds two functions to encode and decode the security label recommended attribute which makes use of the LSM hooks added earlier. It also adds code to grab the label from the file attribute structures and encode the label to be sent back to the server.
--- fs/nfs/dir.c | 4 - fs/nfs/inode.c | 58 +++++++-- fs/nfs/nfs4proc.c | 296 ++++++++++++++++++++++++++++++++++++++++++++-- fs/nfs/nfs4xdr.c | 178 +++++++++++++++++++++++----- fs/nfs/super.c | 17 ++- include/linux/nfs_fs.h | 3 + include/linux/nfs_fs_sb.h | 7 ++ security/selinux/hooks.c | 4 + 8 files changed, 508 insertions(+), 59 deletions(-)
fs/nfs/dir.c +0 -4
@@ -1107,10 +1107,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)nfs_free_fattr (fattr);nfs_free_fhandle (fhandle); -#ifdef CONFIG_NFS_V4_SECURITY_LABEL if (nfs_server_capable (dir,NFS_CAP_SECURITY_LABEL ))nfs4_label_free (label); -#endif out_set_verifier:nfs_set_verifier (dentry,nfs_save_change_attribute (dir));
@@ -1299,10 +1297,8 @@ no_entry: out_unblock_sillyrename:nfs_unblock_sillyrename (parent); out: -#ifdef CONFIG_NFS_V4_SECURITY_LABEL if (nfs_server_capable (dir,NFS_CAP_SECURITY_LABEL ))nfs4_label_free (label); -#endif nfs_free_fattr (fattr);nfs_free_fhandle (fhandle);return res;
fs/nfs/inode.c +50 -8
122 lines not on this page · raw message
fs/nfs/nfs4proc.c +283 -13
466 lines not on this page · raw message
fs/nfs/nfs4xdr.c +146 -32
401 lines not on this page · raw message
fs/nfs/super.c +15 -2
@@ -2419,8 +2419,21 @@ static int nfs_bdi_register(struct nfs_server *server)int nfs_set_sb_security (struct super_block *s,struct dentry *mntroot,struct nfs_mount_info *mount_info) { -return security_sb_set_mnt_opts (s, &mount_info->parsed->lsm_opts, -0 ,NULL ); +int error; +unsigned long kflags =0 , kflags_out =0 ; +if (NFS_SB (s)->caps &NFS_CAP_SECURITY_LABEL ) + kflags |=SECURITY_LSM_NATIVE_LABELS ; + + error =security_sb_set_mnt_opts (s, &mount_info->parsed->lsm_opts, + kflags, &kflags_out); +if (error) + goto err; + +if (NFS_SB (s)->caps &NFS_CAP_SECURITY_LABEL && + !(kflags_out &SECURITY_LSM_NATIVE_LABELS )) +NFS_SB (s)->caps &= ~NFS_CAP_SECURITY_LABEL ; +err: +return error; }EXPORT_SYMBOL_GPL (nfs_set_sb_security);
include/linux/nfs_fs.h +3 -0
@@ -199,6 +199,7 @@ struct nfs_inode {#define NFS_INO_INVALID_ACL 0x0010/* cached acls are invalid */ #define NFS_INO_REVAL_PAGECACHE 0x0020/* must revalidate pagecache */ #define NFS_INO_REVAL_FORCED 0x0040/* force revalidation ignoring a delegation */ +#define NFS_INO_INVALID_LABEL 0x0080/* cached label is invalid */ /* * Bit offsets in flags field
@@ -344,6 +345,8 @@ extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);extern int nfs_revalidate_mapping (struct inode *inode,struct address_space *mapping);extern int nfs_setattr (struct dentry *,struct iattr *);extern void nfs_setattr_update_inode (struct inode *inode,struct iattr *attr); +extern void nfs_setsecurity (struct inode *inode,struct nfs_fattr *fattr, +struct nfs4_label *label);extern struct nfs_open_context *get_nfs_open_context (struct nfs_open_context *ctx);extern void put_nfs_open_context (struct nfs_open_context *ctx);extern struct nfs_open_context *nfs_find_open_context (struct inode *inode,struct rpc_cred *cred,fmode_t mode);
include/linux/nfs_fs_sb.h +7 -0
@@ -145,11 +145,18 @@ struct nfs_server {u32 attr_bitmask[3 ];/* V4 bitmask representing the set of attributes supported on this filesystem */ +u32 attr_bitmask_nl[3 ]; +/* V4 bitmask representing the +set of attributes supported +on this filesystem excluding +the label support bit. */ u32 cache_consistency_bitmask[3 ];/* V4 bitmask representing the subset of change attribute, size, ctime and mtime attributes supported by the server */ +u32 cache_consistency_bitmask_nl[3 ]; +/* As above, excluding label. */ u32 acl_bitmask;/* V4 bitmask representing the ACEs that are supported on this filesystem */
security/selinux/hooks.c +4 -0
@@ -2876,7 +2876,10 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,return ; } + isec->sclass =inode_mode_to_security_class (inode->i_mode); isec->sid = newsid; + isec->initialized =1 ; +return ; }
@@ -2964,6 +2967,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,if (rc)return rc; + isec->sclass =inode_mode_to_security_class (inode->i_mode); isec->sid = newsid; isec->initialized =1 ;return 0 ;
Signature · 1 line
1.7.11.7
PATCH 12/12 NFSD: Server implementation of MAC Labeling
In reply to Steve DicksonFrom: David Quigley <[email protected]>
This patch adds the ability to encode and decode file labels on the server for the purpose of sending them to the client and also to process label change requests from the client.
--- fs/nfs/nfs4proc.c | 50 +++++++++++++++++++++++ fs/nfsd/nfs4proc.c | 33 +++++++++++++++ fs/nfsd/nfs4xdr.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++--- fs/nfsd/nfsd.h | 8 ++-- fs/nfsd/vfs.c | 31 ++++++++++++++ fs/nfsd/vfs.h | 2 + fs/nfsd/xdr4.h | 3 ++ security/security.c | 1 + 8 files changed, 234 insertions(+), 9 deletions(-)
fs/nfs/nfs4proc.c +50 -0
@@ -5461,6 +5461,53 @@ static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,return len; } +#ifdef CONFIG_NFS_V4_SECURITY_LABEL +static inline int nfs4_server_supports_labels (struct nfs_server *server) +{ +return server->caps &NFS_CAP_SECURITY_LABEL ; +} + +static int nfs4_xattr_set_nfs4_label (struct dentry *dentry,const char *key, +const void *buf,size_t buflen, +int flags,int type) +{ +if (security_ismaclabel (key)) +return nfs4_set_security_label (dentry, buf, buflen); + +return -EOPNOTSUPP ; +} + +static int nfs4_xattr_get_nfs4_label (struct dentry *dentry,const char *key, +void *buf,size_t buflen,int type) +{ +if (security_ismaclabel (key)) +return nfs4_get_security_label (dentry->d_inode, buf, buflen); +return -EOPNOTSUPP ; +} + +static size_t nfs4_xattr_list_nfs4_label (struct dentry *dentry,char *list, +size_t list_len,const char *name, +size_t name_len,int type) +{ +size_t len =0 ; + +if (nfs_server_capable (dentry->d_inode,NFS_CAP_SECURITY_LABEL )) { + len =security_inode_listsecurity (dentry->d_inode,NULL ,0 ); +if (list && len <= list_len) +security_inode_listsecurity (dentry->d_inode, list, len); + } +return len; +} + +static const struct xattr_handler nfs4_xattr_nfs4_label_handler = { + .prefix =XATTR_SECURITY_PREFIX , + .list = nfs4_xattr_list_nfs4_label, + .get = nfs4_xattr_get_nfs4_label, + .set = nfs4_xattr_set_nfs4_label, +}; +#endif + +/* * nfs_fhget will use either the mounted_on_fileid or the fileid */
@@ -7201,6 +7248,9 @@ static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {const struct xattr_handler *nfs4_xattr_handlers[] = { &nfs4_xattr_nfs4_acl_handler, +#ifdef CONFIG_NFS_V4_SECURITY_LABEL + &nfs4_xattr_nfs4_label_handler, +#endifNULL };
fs/nfsd/nfs4proc.c +33 -0
@@ -42,6 +42,10 @@#include "current_stateid.h" #include "netns.h" +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL +#include <linux/security.h> +#endif +#define NFSDDBG_FACILITY NFSDDBG_PROCstatic u32 nfsd_attrmask[] = {
@@ -230,6 +234,18 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o (u32 *)open->op_verf.data, &open->op_truncate, &open->op_created); +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL +if (!status && open->op_label !=NULL ) { +struct inode *inode = resfh->fh_dentry->d_inode; + +mutex_lock (&inode->i_mutex); +/* Is it appropriate to just kick back an error? */ + status =security_inode_setsecctx (resfh->fh_dentry, + open->op_label->label, open->op_label->len); +mutex_unlock (&inode->i_mutex); + } +#endif +/* * Following rfc 3530 14.2.16, use the returned bitmask * to indicate which attributes we used to store the
@@ -596,6 +612,18 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, status = nfserr_badtype; } +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL +if (!status && create->cr_label !=NULL ) { +struct inode *inode = resfh.fh_dentry->d_inode; + +mutex_lock (&inode->i_mutex); +/* Is it appropriate to just kick back an error? */ + status =security_inode_setsecctx (resfh.fh_dentry, + create->cr_label->label, create->cr_label->len); +mutex_unlock (&inode->i_mutex); + } +#endif +if (status) goto out;
@@ -888,6 +916,11 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, setattr->sa_acl);if (status) goto out; +if (setattr->sa_label !=NULL ) + status =nfsd4_set_nfs4_label (rqstp, &cstate->current_fh, + setattr->sa_label); +if (status) + goto out; status =nfsd_setattr (rqstp, &cstate->current_fh, &setattr->sa_iattr,0 , (time_t )0 ); out:
fs/nfsd/nfs4xdr.c +110 -5
175 lines not on this page · raw message
fs/nfsd/nfsd.h +4 -4
@@ -308,10 +308,10 @@ void nfsd_lockd_shutdown(void); | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP | FATTR4_WORD1_RAWDEV \ | FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL \ | FATTR4_WORD1_SPACE_USED | FATTR4_WORD1_TIME_ACCESS | FATTR4_WORD1_TIME_ACCESS_SET \ - | FATTR4_WORD1_TIME_DELTA | FATTR4_WORD1_TIME_METADATA \ - | FATTR4_WORD1_TIME_MODIFY | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID) + | FATTR4_WORD1_TIME_DELTA | FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY \ + | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_MOUNTED_ON_FILEID) -#define NFSD4_SUPPORTED_ATTRS_WORD2 0 +#define NFSD4_SUPPORTED_ATTRS_WORD2 FATTR4_WORD2_SECURITY_LABEL#define NFSD4_1_SUPPORTED_ATTRS_WORD0 \ NFSD4_SUPPORTED_ATTRS_WORD0
@@ -350,7 +350,7 @@ static inline u32 nfsd_suppattrs2(u32 minorversion)#define NFSD_WRITEABLE_ATTRS_WORD1 \ (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) -#define NFSD_WRITEABLE_ATTRS_WORD2 0 +#define NFSD_WRITEABLE_ATTRS_WORD2 FATTR4_WORD2_SECURITY_LABEL#define NFSD_SUPPATTR_EXCLCREAT_WORD0 \ NFSD_WRITEABLE_ATTRS_WORD0
fs/nfsd/vfs.c +31 -0
@@ -28,6 +28,7 @@#include <asm/uaccess.h> #include <linux/exportfs.h> #include <linux/writeback.h> +#include <linux/security.h> #ifdef CONFIG_NFSD_V3 #include "xdr3.h"
@@ -621,6 +622,36 @@ int nfsd4_is_junction(struct dentry *dentry)return 0 ;return 1 ; } + +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL +__be32 nfsd4_set_nfs4_label (struct svc_rqst *rqstp,struct svc_fh *fhp, +struct nfs4_label *label) +{ +__be32 error; +int host_error; +struct dentry *dentry; + +/* Get inode */ +/* XXX: should we have a MAY_SSECCTX? */ + error =fh_verify (rqstp, fhp,0 /* S_IFREG */ ,NFSD_MAY_SATTR ); +if (error) +return error; + + dentry = fhp->fh_dentry; + +mutex_lock (&dentry->d_inode->i_mutex); + host_error =security_inode_setsecctx (dentry, label->label, label->len); +mutex_unlock (&dentry->d_inode->i_mutex); +return nfserrno (host_error); +} +#else +__be32 nfsd4_set_nfs4_label (struct svc_rqst *rqstp,struct svc_fh *fhp, +struct nfs4_label *label) +{ +return -EOPNOTSUPP ; +} +#endif +#endif /* defined(CONFIG_NFSD_V4) */ #ifdef CONFIG_NFSD_V3
fs/nfsd/vfs.h +2 -0
@@ -55,6 +55,8 @@ int nfsd_mountpoint(struct dentry *, struct svc_export *);__be32 nfsd4_set_nfs4_acl (struct svc_rqst *,struct svc_fh *,struct nfs4_acl *);int nfsd4_get_nfs4_acl (struct svc_rqst *,struct dentry *,struct nfs4_acl **); +__be32 nfsd4_set_nfs4_label (struct svc_rqst *,struct svc_fh *, +struct nfs4_label *);#endif /* CONFIG_NFSD_V4 */ __be32 nfsd_create(struct svc_rqst *, struct svc_fh *, char *name, int len, struct iattr *attrs,
fs/nfsd/xdr4.h +3 -0
@@ -118,6 +118,7 @@ struct nfsd4_create {struct iattr cr_iattr;/* request */ struct nfsd4_change_info cr_cinfo;/* response */ struct nfs4_acl *cr_acl; +struct nfs4_label *cr_label; };#define cr_linklen u.link.namelen#define cr_linkname u.link.name
@@ -246,6 +247,7 @@ struct nfsd4_open {struct nfs4_file *op_file;/* used during processing */ struct nfs4_ol_stateid *op_stp;/* used during processing */ struct nfs4_acl *op_acl; +struct nfs4_label *op_label; };#define op_iattr iattr
@@ -330,6 +332,7 @@ struct nfsd4_setattr {u32 sa_bmval[3 ];/* request */ struct iattr sa_iattr;/* request */ struct nfs4_acl *sa_acl; +struct nfs4_label *sa_label; };struct nfsd4_setclientid {
security/security.c +1 -0
@@ -660,6 +660,7 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t bufferreturn 0 ;return security_ops->inode_listsecurity (inode, buffer, buffer_size); } +EXPORT_SYMBOL (security_inode_listsecurity);void security_inode_getsecid (const struct inode *inode,u32 *secid) {
Signature · 1 line
1.7.11.7