diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-06-28 16:29:51 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-06-28 16:29:51 -0400 |
commit | 959d921f5eb8878ea16049a7f6e9bcbb6dfbcb88 (patch) | |
tree | 83fb4d2756fab97f508b5dccaac7578ba63a76e0 | |
parent | f112bb48994e56868870a080773c392f774fa9a2 (diff) | |
parent | 7017310ad737880d8520a7fc7e25a26b2e7e37f0 (diff) |
Merge branch 'labeled-nfs' into linux-next
* labeled-nfs:
NFS: Apply v4.1 capabilities to v4.2
NFS: Add in v4.2 callback operation
NFS: Make callbacks minor version generic
Kconfig: Add Kconfig entry for Labeled NFS V4 client
NFS: Extend NFS xattr handlers to accept the security namespace
NFS: Client implementation of Labeled-NFS
NFS: Add label lifecycle management
NFS:Add labels to client function prototypes
NFSv4: Extend fattr bitmaps to support all 3 words
NFSv4: Introduce new label structure
NFSv4: Add label recommended attribute and NFSv4 flags
NFSv4.2: Added NFS v4.2 support to the NFS client
SELinux: Add new labeling type native labels
LSM: Add flags field to security_sb_set_mnt_opts for in kernel mount data.
Security: Add Hook to test if the particular xattr is part of a MAC model.
Security: Add hook to calculate context based on a negative dentry.
NFS: Add NFSv4.2 protocol constants
Conflicts:
fs/nfs/nfs4proc.c
-rw-r--r-- | fs/nfs/Kconfig | 14 | ||||
-rw-r--r-- | fs/nfs/callback.c | 1 | ||||
-rw-r--r-- | fs/nfs/callback.h | 3 | ||||
-rw-r--r-- | fs/nfs/callback_proc.c | 3 | ||||
-rw-r--r-- | fs/nfs/callback_xdr.c | 52 | ||||
-rw-r--r-- | fs/nfs/client.c | 2 | ||||
-rw-r--r-- | fs/nfs/dir.c | 49 | ||||
-rw-r--r-- | fs/nfs/getroot.c | 2 | ||||
-rw-r--r-- | fs/nfs/inode.c | 109 | ||||
-rw-r--r-- | fs/nfs/internal.h | 2 | ||||
-rw-r--r-- | fs/nfs/namespace.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 7 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 6 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 11 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 529 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 174 | ||||
-rw-r--r-- | fs/nfs/proc.c | 13 | ||||
-rw-r--r-- | fs/nfs/super.c | 24 | ||||
-rw-r--r-- | fs/nfsd/nfsd.h | 6 | ||||
-rw-r--r-- | include/linux/nfs4.h | 22 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 26 | ||||
-rw-r--r-- | include/linux/nfs_fs_sb.h | 8 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 19 | ||||
-rw-r--r-- | include/linux/security.h | 57 | ||||
-rw-r--r-- | security/capability.c | 19 | ||||
-rw-r--r-- | security/security.c | 24 | ||||
-rw-r--r-- | security/selinux/hooks.c | 92 | ||||
-rw-r--r-- | security/selinux/include/security.h | 2 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 5 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 11 |
30 files changed, 1123 insertions, 171 deletions
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 13ca196385f5..b5e80b0af315 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig | |||
@@ -104,6 +104,15 @@ config NFS_V4_1 | |||
104 | 104 | ||
105 | If unsure, say N. | 105 | If unsure, say N. |
106 | 106 | ||
107 | config NFS_V4_2 | ||
108 | bool "NFS client support for NFSv4.2" | ||
109 | depends on NFS_V4_1 | ||
110 | help | ||
111 | This option enables support for minor version 2 of the NFSv4 protocol | ||
112 | in the kernel's NFS client. | ||
113 | |||
114 | If unsure, say N. | ||
115 | |||
107 | config PNFS_FILE_LAYOUT | 116 | config PNFS_FILE_LAYOUT |
108 | tristate | 117 | tristate |
109 | depends on NFS_V4_1 | 118 | depends on NFS_V4_1 |
@@ -131,6 +140,11 @@ config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN | |||
131 | If the NFS client is unchanged from the upstream kernel, this | 140 | If the NFS client is unchanged from the upstream kernel, this |
132 | option should be set to the default "kernel.org". | 141 | option should be set to the default "kernel.org". |
133 | 142 | ||
143 | config NFS_V4_SECURITY_LABEL | ||
144 | bool | ||
145 | depends on NFS_V4_2 && SECURITY | ||
146 | default y | ||
147 | |||
134 | config ROOT_NFS | 148 | config ROOT_NFS |
135 | bool "Root file system on NFS" | 149 | bool "Root file system on NFS" |
136 | depends on NFS_FS=y && IP_PNP | 150 | depends on NFS_FS=y && IP_PNP |
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index cff089a412c7..78e368d8186d 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -282,6 +282,7 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct n | |||
282 | ret = nfs4_callback_up_net(serv, net); | 282 | ret = nfs4_callback_up_net(serv, net); |
283 | break; | 283 | break; |
284 | case 1: | 284 | case 1: |
285 | case 2: | ||
285 | ret = nfs41_callback_up_net(serv, net); | 286 | ret = nfs41_callback_up_net(serv, net); |
286 | break; | 287 | break; |
287 | default: | 288 | default: |
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index efd54f0a4c46..84326e9fb47a 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h | |||
@@ -32,6 +32,8 @@ enum nfs4_callback_opnum { | |||
32 | OP_CB_WANTS_CANCELLED = 12, | 32 | OP_CB_WANTS_CANCELLED = 12, |
33 | OP_CB_NOTIFY_LOCK = 13, | 33 | OP_CB_NOTIFY_LOCK = 13, |
34 | OP_CB_NOTIFY_DEVICEID = 14, | 34 | OP_CB_NOTIFY_DEVICEID = 14, |
35 | /* Callback operations new to NFSv4.2 */ | ||
36 | OP_CB_OFFLOAD = 15, | ||
35 | OP_CB_ILLEGAL = 10044, | 37 | OP_CB_ILLEGAL = 10044, |
36 | }; | 38 | }; |
37 | 39 | ||
@@ -39,6 +41,7 @@ struct cb_process_state { | |||
39 | __be32 drc_status; | 41 | __be32 drc_status; |
40 | struct nfs_client *clp; | 42 | struct nfs_client *clp; |
41 | u32 slotid; | 43 | u32 slotid; |
44 | u32 minorversion; | ||
42 | struct net *net; | 45 | struct net *net; |
43 | }; | 46 | }; |
44 | 47 | ||
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 0bc27684ebfa..e6ebc4c38c81 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -406,7 +406,8 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args, | |||
406 | int i; | 406 | int i; |
407 | __be32 status = htonl(NFS4ERR_BADSESSION); | 407 | __be32 status = htonl(NFS4ERR_BADSESSION); |
408 | 408 | ||
409 | clp = nfs4_find_client_sessionid(cps->net, args->csa_addr, &args->csa_sessionid); | 409 | clp = nfs4_find_client_sessionid(cps->net, args->csa_addr, |
410 | &args->csa_sessionid, cps->minorversion); | ||
410 | if (clp == NULL) | 411 | if (clp == NULL) |
411 | goto out; | 412 | goto out; |
412 | 413 | ||
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index a35582c9d444..f4ccfe6521ec 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
@@ -166,9 +166,9 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound | |||
166 | if (unlikely(p == NULL)) | 166 | if (unlikely(p == NULL)) |
167 | return htonl(NFS4ERR_RESOURCE); | 167 | return htonl(NFS4ERR_RESOURCE); |
168 | hdr->minorversion = ntohl(*p++); | 168 | hdr->minorversion = ntohl(*p++); |
169 | /* Check minor version is zero or one. */ | 169 | /* Check for minor version support */ |
170 | if (hdr->minorversion <= 1) { | 170 | if (hdr->minorversion <= NFS4_MAX_MINOR_VERSION) { |
171 | hdr->cb_ident = ntohl(*p++); /* ignored by v4.1 */ | 171 | hdr->cb_ident = ntohl(*p++); /* ignored by v4.1 and v4.2 */ |
172 | } else { | 172 | } else { |
173 | pr_warn_ratelimited("NFS: %s: NFSv4 server callback with " | 173 | pr_warn_ratelimited("NFS: %s: NFSv4 server callback with " |
174 | "illegal minor version %u!\n", | 174 | "illegal minor version %u!\n", |
@@ -786,6 +786,26 @@ static void nfs4_cb_free_slot(struct cb_process_state *cps) | |||
786 | } | 786 | } |
787 | #endif /* CONFIG_NFS_V4_1 */ | 787 | #endif /* CONFIG_NFS_V4_1 */ |
788 | 788 | ||
789 | #ifdef CONFIG_NFS_V4_2 | ||
790 | static __be32 | ||
791 | preprocess_nfs42_op(int nop, unsigned int op_nr, struct callback_op **op) | ||
792 | { | ||
793 | __be32 status = preprocess_nfs41_op(nop, op_nr, op); | ||
794 | if (status != htonl(NFS4ERR_OP_ILLEGAL)) | ||
795 | return status; | ||
796 | |||
797 | if (op_nr == OP_CB_OFFLOAD) | ||
798 | return htonl(NFS4ERR_NOTSUPP); | ||
799 | return htonl(NFS4ERR_OP_ILLEGAL); | ||
800 | } | ||
801 | #else /* CONFIG_NFS_V4_2 */ | ||
802 | static __be32 | ||
803 | preprocess_nfs42_op(int nop, unsigned int op_nr, struct callback_op **op) | ||
804 | { | ||
805 | return htonl(NFS4ERR_MINOR_VERS_MISMATCH); | ||
806 | } | ||
807 | #endif /* CONFIG_NFS_V4_2 */ | ||
808 | |||
789 | static __be32 | 809 | static __be32 |
790 | preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op) | 810 | preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op) |
791 | { | 811 | { |
@@ -801,8 +821,7 @@ preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op) | |||
801 | return htonl(NFS_OK); | 821 | return htonl(NFS_OK); |
802 | } | 822 | } |
803 | 823 | ||
804 | static __be32 process_op(uint32_t minorversion, int nop, | 824 | static __be32 process_op(int nop, struct svc_rqst *rqstp, |
805 | struct svc_rqst *rqstp, | ||
806 | struct xdr_stream *xdr_in, void *argp, | 825 | struct xdr_stream *xdr_in, void *argp, |
807 | struct xdr_stream *xdr_out, void *resp, | 826 | struct xdr_stream *xdr_out, void *resp, |
808 | struct cb_process_state *cps) | 827 | struct cb_process_state *cps) |
@@ -819,10 +838,22 @@ static __be32 process_op(uint32_t minorversion, int nop, | |||
819 | return status; | 838 | return status; |
820 | 839 | ||
821 | dprintk("%s: minorversion=%d nop=%d op_nr=%u\n", | 840 | dprintk("%s: minorversion=%d nop=%d op_nr=%u\n", |
822 | __func__, minorversion, nop, op_nr); | 841 | __func__, cps->minorversion, nop, op_nr); |
842 | |||
843 | switch (cps->minorversion) { | ||
844 | case 0: | ||
845 | status = preprocess_nfs4_op(op_nr, &op); | ||
846 | break; | ||
847 | case 1: | ||
848 | status = preprocess_nfs41_op(nop, op_nr, &op); | ||
849 | break; | ||
850 | case 2: | ||
851 | status = preprocess_nfs42_op(nop, op_nr, &op); | ||
852 | break; | ||
853 | default: | ||
854 | status = htonl(NFS4ERR_MINOR_VERS_MISMATCH); | ||
855 | } | ||
823 | 856 | ||
824 | status = minorversion ? preprocess_nfs41_op(nop, op_nr, &op) : | ||
825 | preprocess_nfs4_op(op_nr, &op); | ||
826 | if (status == htonl(NFS4ERR_OP_ILLEGAL)) | 857 | if (status == htonl(NFS4ERR_OP_ILLEGAL)) |
827 | op_nr = OP_CB_ILLEGAL; | 858 | op_nr = OP_CB_ILLEGAL; |
828 | if (status) | 859 | if (status) |
@@ -885,14 +916,15 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r | |||
885 | return rpc_drop_reply; | 916 | return rpc_drop_reply; |
886 | } | 917 | } |
887 | 918 | ||
919 | cps.minorversion = hdr_arg.minorversion; | ||
888 | hdr_res.taglen = hdr_arg.taglen; | 920 | hdr_res.taglen = hdr_arg.taglen; |
889 | hdr_res.tag = hdr_arg.tag; | 921 | hdr_res.tag = hdr_arg.tag; |
890 | if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0) | 922 | if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0) |
891 | return rpc_system_err; | 923 | return rpc_system_err; |
892 | 924 | ||
893 | while (status == 0 && nops != hdr_arg.nops) { | 925 | while (status == 0 && nops != hdr_arg.nops) { |
894 | status = process_op(hdr_arg.minorversion, nops, rqstp, | 926 | status = process_op(nops, rqstp, &xdr_in, |
895 | &xdr_in, argp, &xdr_out, resp, &cps); | 927 | argp, &xdr_out, resp, &cps); |
896 | nops++; | 928 | nops++; |
897 | } | 929 | } |
898 | 930 | ||
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index dbb65fb9e82d..340b1eff0267 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -1074,7 +1074,7 @@ struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info, | |||
1074 | } | 1074 | } |
1075 | 1075 | ||
1076 | if (!(fattr->valid & NFS_ATTR_FATTR)) { | 1076 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
1077 | error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, fattr); | 1077 | error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, fattr, NULL); |
1078 | if (error < 0) { | 1078 | if (error < 0) { |
1079 | dprintk("nfs_create_server: getattr error = %d\n", -error); | 1079 | dprintk("nfs_create_server: getattr error = %d\n", -error); |
1080 | goto error; | 1080 | goto error; |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c662ff6befd6..c3f21888654f 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -435,6 +435,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
435 | struct dentry *alias; | 435 | struct dentry *alias; |
436 | struct inode *dir = parent->d_inode; | 436 | struct inode *dir = parent->d_inode; |
437 | struct inode *inode; | 437 | struct inode *inode; |
438 | int status; | ||
438 | 439 | ||
439 | if (filename.name[0] == '.') { | 440 | if (filename.name[0] == '.') { |
440 | if (filename.len == 1) | 441 | if (filename.len == 1) |
@@ -447,7 +448,9 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
447 | dentry = d_lookup(parent, &filename); | 448 | dentry = d_lookup(parent, &filename); |
448 | if (dentry != NULL) { | 449 | if (dentry != NULL) { |
449 | if (nfs_same_file(dentry, entry)) { | 450 | if (nfs_same_file(dentry, entry)) { |
450 | nfs_refresh_inode(dentry->d_inode, entry->fattr); | 451 | status = nfs_refresh_inode(dentry->d_inode, entry->fattr); |
452 | if (!status) | ||
453 | nfs_setsecurity(dentry->d_inode, entry->fattr, entry->label); | ||
451 | goto out; | 454 | goto out; |
452 | } else { | 455 | } else { |
453 | if (d_invalidate(dentry) != 0) | 456 | if (d_invalidate(dentry) != 0) |
@@ -460,7 +463,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
460 | if (dentry == NULL) | 463 | if (dentry == NULL) |
461 | return; | 464 | return; |
462 | 465 | ||
463 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); | 466 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr, entry->label); |
464 | if (IS_ERR(inode)) | 467 | if (IS_ERR(inode)) |
465 | goto out; | 468 | goto out; |
466 | 469 | ||
@@ -585,10 +588,16 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
585 | if (entry.fh == NULL || entry.fattr == NULL) | 588 | if (entry.fh == NULL || entry.fattr == NULL) |
586 | goto out; | 589 | goto out; |
587 | 590 | ||
591 | entry.label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT); | ||
592 | if (IS_ERR(entry.label)) { | ||
593 | status = PTR_ERR(entry.label); | ||
594 | goto out; | ||
595 | } | ||
596 | |||
588 | array = nfs_readdir_get_array(page); | 597 | array = nfs_readdir_get_array(page); |
589 | if (IS_ERR(array)) { | 598 | if (IS_ERR(array)) { |
590 | status = PTR_ERR(array); | 599 | status = PTR_ERR(array); |
591 | goto out; | 600 | goto out_label_free; |
592 | } | 601 | } |
593 | memset(array, 0, sizeof(struct nfs_cache_array)); | 602 | memset(array, 0, sizeof(struct nfs_cache_array)); |
594 | array->eof_index = -1; | 603 | array->eof_index = -1; |
@@ -614,6 +623,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
614 | nfs_readdir_free_large_page(pages_ptr, pages, array_size); | 623 | nfs_readdir_free_large_page(pages_ptr, pages, array_size); |
615 | out_release_array: | 624 | out_release_array: |
616 | nfs_readdir_release_array(page); | 625 | nfs_readdir_release_array(page); |
626 | out_label_free: | ||
627 | nfs4_label_free(entry.label); | ||
617 | out: | 628 | out: |
618 | nfs_free_fattr(entry.fattr); | 629 | nfs_free_fattr(entry.fattr); |
619 | nfs_free_fhandle(entry.fh); | 630 | nfs_free_fhandle(entry.fh); |
@@ -1040,6 +1051,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1040 | struct dentry *parent; | 1051 | struct dentry *parent; |
1041 | struct nfs_fh *fhandle = NULL; | 1052 | struct nfs_fh *fhandle = NULL; |
1042 | struct nfs_fattr *fattr = NULL; | 1053 | struct nfs_fattr *fattr = NULL; |
1054 | struct nfs4_label *label = NULL; | ||
1043 | int error; | 1055 | int error; |
1044 | 1056 | ||
1045 | if (flags & LOOKUP_RCU) | 1057 | if (flags & LOOKUP_RCU) |
@@ -1082,7 +1094,11 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1082 | if (fhandle == NULL || fattr == NULL) | 1094 | if (fhandle == NULL || fattr == NULL) |
1083 | goto out_error; | 1095 | goto out_error; |
1084 | 1096 | ||
1085 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1097 | label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT); |
1098 | if (IS_ERR(label)) | ||
1099 | goto out_error; | ||
1100 | |||
1101 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); | ||
1086 | if (error) | 1102 | if (error) |
1087 | goto out_bad; | 1103 | goto out_bad; |
1088 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) | 1104 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) |
@@ -1090,8 +1106,12 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1090 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) | 1106 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) |
1091 | goto out_bad; | 1107 | goto out_bad; |
1092 | 1108 | ||
1109 | nfs_setsecurity(inode, fattr, label); | ||
1110 | |||
1093 | nfs_free_fattr(fattr); | 1111 | nfs_free_fattr(fattr); |
1094 | nfs_free_fhandle(fhandle); | 1112 | nfs_free_fhandle(fhandle); |
1113 | nfs4_label_free(label); | ||
1114 | |||
1095 | out_set_verifier: | 1115 | out_set_verifier: |
1096 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1116 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1097 | out_valid: | 1117 | out_valid: |
@@ -1108,6 +1128,7 @@ out_zap_parent: | |||
1108 | out_bad: | 1128 | out_bad: |
1109 | nfs_free_fattr(fattr); | 1129 | nfs_free_fattr(fattr); |
1110 | nfs_free_fhandle(fhandle); | 1130 | nfs_free_fhandle(fhandle); |
1131 | nfs4_label_free(label); | ||
1111 | nfs_mark_for_revalidate(dir); | 1132 | nfs_mark_for_revalidate(dir); |
1112 | if (inode && S_ISDIR(inode->i_mode)) { | 1133 | if (inode && S_ISDIR(inode->i_mode)) { |
1113 | /* Purge readdir caches. */ | 1134 | /* Purge readdir caches. */ |
@@ -1128,6 +1149,7 @@ out_zap_parent: | |||
1128 | out_error: | 1149 | out_error: |
1129 | nfs_free_fattr(fattr); | 1150 | nfs_free_fattr(fattr); |
1130 | nfs_free_fhandle(fhandle); | 1151 | nfs_free_fhandle(fhandle); |
1152 | nfs4_label_free(label); | ||
1131 | dput(parent); | 1153 | dput(parent); |
1132 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", | 1154 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", |
1133 | __func__, dentry->d_parent->d_name.name, | 1155 | __func__, dentry->d_parent->d_name.name, |
@@ -1256,6 +1278,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
1256 | struct inode *inode = NULL; | 1278 | struct inode *inode = NULL; |
1257 | struct nfs_fh *fhandle = NULL; | 1279 | struct nfs_fh *fhandle = NULL; |
1258 | struct nfs_fattr *fattr = NULL; | 1280 | struct nfs_fattr *fattr = NULL; |
1281 | struct nfs4_label *label = NULL; | ||
1259 | int error; | 1282 | int error; |
1260 | 1283 | ||
1261 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", | 1284 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", |
@@ -1282,17 +1305,21 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
1282 | if (fhandle == NULL || fattr == NULL) | 1305 | if (fhandle == NULL || fattr == NULL) |
1283 | goto out; | 1306 | goto out; |
1284 | 1307 | ||
1308 | label = nfs4_label_alloc(NFS_SERVER(dir), GFP_NOWAIT); | ||
1309 | if (IS_ERR(label)) | ||
1310 | goto out; | ||
1311 | |||
1285 | parent = dentry->d_parent; | 1312 | parent = dentry->d_parent; |
1286 | /* Protect against concurrent sillydeletes */ | 1313 | /* Protect against concurrent sillydeletes */ |
1287 | nfs_block_sillyrename(parent); | 1314 | nfs_block_sillyrename(parent); |
1288 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1315 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); |
1289 | if (error == -ENOENT) | 1316 | if (error == -ENOENT) |
1290 | goto no_entry; | 1317 | goto no_entry; |
1291 | if (error < 0) { | 1318 | if (error < 0) { |
1292 | res = ERR_PTR(error); | 1319 | res = ERR_PTR(error); |
1293 | goto out_unblock_sillyrename; | 1320 | goto out_unblock_sillyrename; |
1294 | } | 1321 | } |
1295 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1322 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label); |
1296 | res = ERR_CAST(inode); | 1323 | res = ERR_CAST(inode); |
1297 | if (IS_ERR(res)) | 1324 | if (IS_ERR(res)) |
1298 | goto out_unblock_sillyrename; | 1325 | goto out_unblock_sillyrename; |
@@ -1310,6 +1337,7 @@ no_entry: | |||
1310 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1337 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1311 | out_unblock_sillyrename: | 1338 | out_unblock_sillyrename: |
1312 | nfs_unblock_sillyrename(parent); | 1339 | nfs_unblock_sillyrename(parent); |
1340 | nfs4_label_free(label); | ||
1313 | out: | 1341 | out: |
1314 | nfs_free_fattr(fattr); | 1342 | nfs_free_fattr(fattr); |
1315 | nfs_free_fhandle(fhandle); | 1343 | nfs_free_fhandle(fhandle); |
@@ -1508,7 +1536,8 @@ no_open: | |||
1508 | * Code common to create, mkdir, and mknod. | 1536 | * Code common to create, mkdir, and mknod. |
1509 | */ | 1537 | */ |
1510 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | 1538 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, |
1511 | struct nfs_fattr *fattr) | 1539 | struct nfs_fattr *fattr, |
1540 | struct nfs4_label *label) | ||
1512 | { | 1541 | { |
1513 | struct dentry *parent = dget_parent(dentry); | 1542 | struct dentry *parent = dget_parent(dentry); |
1514 | struct inode *dir = parent->d_inode; | 1543 | struct inode *dir = parent->d_inode; |
@@ -1521,18 +1550,18 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | |||
1521 | if (dentry->d_inode) | 1550 | if (dentry->d_inode) |
1522 | goto out; | 1551 | goto out; |
1523 | if (fhandle->size == 0) { | 1552 | if (fhandle->size == 0) { |
1524 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1553 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, NULL); |
1525 | if (error) | 1554 | if (error) |
1526 | goto out_error; | 1555 | goto out_error; |
1527 | } | 1556 | } |
1528 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1557 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1529 | if (!(fattr->valid & NFS_ATTR_FATTR)) { | 1558 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
1530 | struct nfs_server *server = NFS_SB(dentry->d_sb); | 1559 | struct nfs_server *server = NFS_SB(dentry->d_sb); |
1531 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); | 1560 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr, NULL); |
1532 | if (error < 0) | 1561 | if (error < 0) |
1533 | goto out_error; | 1562 | goto out_error; |
1534 | } | 1563 | } |
1535 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1564 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label); |
1536 | error = PTR_ERR(inode); | 1565 | error = PTR_ERR(inode); |
1537 | if (IS_ERR(inode)) | 1566 | if (IS_ERR(inode)) |
1538 | goto out_error; | 1567 | goto out_error; |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 44efaa8c5f78..66984a9aafaa 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -95,7 +95,7 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh, | |||
95 | goto out; | 95 | goto out; |
96 | } | 96 | } |
97 | 97 | ||
98 | inode = nfs_fhget(sb, mntfh, fsinfo.fattr); | 98 | inode = nfs_fhget(sb, mntfh, fsinfo.fattr, NULL); |
99 | if (IS_ERR(inode)) { | 99 | if (IS_ERR(inode)) { |
100 | dprintk("nfs_get_root: get root inode failed\n"); | 100 | dprintk("nfs_get_root: get root inode failed\n"); |
101 | ret = ERR_CAST(inode); | 101 | ret = ERR_CAST(inode); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e09920cacd8b..8ea62be3fefe 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -161,11 +161,19 @@ static void nfs_zap_caches_locked(struct inode *inode) | |||
161 | 161 | ||
162 | memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); | 162 | memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); |
163 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { | 163 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { |
164 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | ||
165 | nfs_fscache_invalidate(inode); | 164 | nfs_fscache_invalidate(inode); |
166 | } else { | 165 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR |
167 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 166 | | NFS_INO_INVALID_LABEL |
168 | } | 167 | | NFS_INO_INVALID_DATA |
168 | | NFS_INO_INVALID_ACCESS | ||
169 | | NFS_INO_INVALID_ACL | ||
170 | | NFS_INO_REVAL_PAGECACHE; | ||
171 | } else | ||
172 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | ||
173 | | NFS_INO_INVALID_LABEL | ||
174 | | NFS_INO_INVALID_ACCESS | ||
175 | | NFS_INO_INVALID_ACL | ||
176 | | NFS_INO_REVAL_PAGECACHE; | ||
169 | } | 177 | } |
170 | 178 | ||
171 | void nfs_zap_caches(struct inode *inode) | 179 | void nfs_zap_caches(struct inode *inode) |
@@ -256,12 +264,72 @@ nfs_init_locked(struct inode *inode, void *opaque) | |||
256 | return 0; | 264 | return 0; |
257 | } | 265 | } |
258 | 266 | ||
267 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
268 | void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | ||
269 | struct nfs4_label *label) | ||
270 | { | ||
271 | int error; | ||
272 | |||
273 | if (label == NULL) | ||
274 | return; | ||
275 | |||
276 | if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL) == 0) | ||
277 | return; | ||
278 | |||
279 | if (NFS_SERVER(inode)->nfs_client->cl_minorversion < 2) | ||
280 | return; | ||
281 | |||
282 | if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) && inode->i_security) { | ||
283 | error = security_inode_notifysecctx(inode, label->label, | ||
284 | label->len); | ||
285 | if (error) | ||
286 | printk(KERN_ERR "%s() %s %d " | ||
287 | "security_inode_notifysecctx() %d\n", | ||
288 | __func__, | ||
289 | (char *)label->label, | ||
290 | label->len, error); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) | ||
295 | { | ||
296 | struct nfs4_label *label = NULL; | ||
297 | int minor_version = server->nfs_client->cl_minorversion; | ||
298 | |||
299 | if (minor_version < 2) | ||
300 | return label; | ||
301 | |||
302 | if (!(server->caps & NFS_CAP_SECURITY_LABEL)) | ||
303 | return label; | ||
304 | |||
305 | label = kzalloc(sizeof(struct nfs4_label), flags); | ||
306 | if (label == NULL) | ||
307 | return ERR_PTR(-ENOMEM); | ||
308 | |||
309 | label->label = kzalloc(NFS4_MAXLABELLEN, flags); | ||
310 | if (label->label == NULL) { | ||
311 | kfree(label); | ||
312 | return ERR_PTR(-ENOMEM); | ||
313 | } | ||
314 | label->len = NFS4_MAXLABELLEN; | ||
315 | |||
316 | return label; | ||
317 | } | ||
318 | EXPORT_SYMBOL_GPL(nfs4_label_alloc); | ||
319 | #else | ||
320 | void inline nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | ||
321 | struct nfs4_label *label) | ||
322 | { | ||
323 | } | ||
324 | #endif | ||
325 | EXPORT_SYMBOL_GPL(nfs_setsecurity); | ||
326 | |||
259 | /* | 327 | /* |
260 | * This is our front-end to iget that looks up inodes by file handle | 328 | * This is our front-end to iget that looks up inodes by file handle |
261 | * instead of inode number. | 329 | * instead of inode number. |
262 | */ | 330 | */ |
263 | struct inode * | 331 | struct inode * |
264 | nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | 332 | nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, struct nfs4_label *label) |
265 | { | 333 | { |
266 | struct nfs_find_desc desc = { | 334 | struct nfs_find_desc desc = { |
267 | .fh = fh, | 335 | .fh = fh, |
@@ -383,6 +451,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
383 | */ | 451 | */ |
384 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 452 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
385 | } | 453 | } |
454 | |||
455 | nfs_setsecurity(inode, fattr, label); | ||
456 | |||
386 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 457 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
387 | nfsi->attrtimeo_timestamp = now; | 458 | nfsi->attrtimeo_timestamp = now; |
388 | nfsi->access_cache = RB_ROOT; | 459 | nfsi->access_cache = RB_ROOT; |
@@ -392,6 +463,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
392 | unlock_new_inode(inode); | 463 | unlock_new_inode(inode); |
393 | } else | 464 | } else |
394 | nfs_refresh_inode(inode, fattr); | 465 | nfs_refresh_inode(inode, fattr); |
466 | nfs_setsecurity(inode, fattr, label); | ||
395 | dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n", | 467 | dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n", |
396 | inode->i_sb->s_id, | 468 | inode->i_sb->s_id, |
397 | (long long)NFS_FILEID(inode), | 469 | (long long)NFS_FILEID(inode), |
@@ -448,7 +520,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
448 | NFS_PROTO(inode)->return_delegation(inode); | 520 | NFS_PROTO(inode)->return_delegation(inode); |
449 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); | 521 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); |
450 | if (error == 0) | 522 | if (error == 0) |
451 | nfs_refresh_inode(inode, fattr); | 523 | error = nfs_refresh_inode(inode, fattr); |
452 | nfs_free_fattr(fattr); | 524 | nfs_free_fattr(fattr); |
453 | out: | 525 | out: |
454 | return error; | 526 | return error; |
@@ -797,6 +869,7 @@ int | |||
797 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 869 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
798 | { | 870 | { |
799 | int status = -ESTALE; | 871 | int status = -ESTALE; |
872 | struct nfs4_label *label = NULL; | ||
800 | struct nfs_fattr *fattr = NULL; | 873 | struct nfs_fattr *fattr = NULL; |
801 | struct nfs_inode *nfsi = NFS_I(inode); | 874 | struct nfs_inode *nfsi = NFS_I(inode); |
802 | 875 | ||
@@ -814,7 +887,14 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
814 | goto out; | 887 | goto out; |
815 | 888 | ||
816 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | 889 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); |
817 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr); | 890 | |
891 | label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL); | ||
892 | if (IS_ERR(label)) { | ||
893 | status = PTR_ERR(label); | ||
894 | goto out; | ||
895 | } | ||
896 | |||
897 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr, label); | ||
818 | if (status != 0) { | 898 | if (status != 0) { |
819 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", | 899 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", |
820 | inode->i_sb->s_id, | 900 | inode->i_sb->s_id, |
@@ -824,7 +904,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
824 | if (!S_ISDIR(inode->i_mode)) | 904 | if (!S_ISDIR(inode->i_mode)) |
825 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); | 905 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); |
826 | } | 906 | } |
827 | goto out; | 907 | goto err_out; |
828 | } | 908 | } |
829 | 909 | ||
830 | status = nfs_refresh_inode(inode, fattr); | 910 | status = nfs_refresh_inode(inode, fattr); |
@@ -832,7 +912,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
832 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 912 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
833 | inode->i_sb->s_id, | 913 | inode->i_sb->s_id, |
834 | (long long)NFS_FILEID(inode), status); | 914 | (long long)NFS_FILEID(inode), status); |
835 | goto out; | 915 | goto err_out; |
836 | } | 916 | } |
837 | 917 | ||
838 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) | 918 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) |
@@ -842,7 +922,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
842 | inode->i_sb->s_id, | 922 | inode->i_sb->s_id, |
843 | (long long)NFS_FILEID(inode)); | 923 | (long long)NFS_FILEID(inode)); |
844 | 924 | ||
845 | out: | 925 | err_out: |
926 | nfs4_label_free(label); | ||
927 | out: | ||
846 | nfs_free_fattr(fattr); | 928 | nfs_free_fattr(fattr); |
847 | return status; | 929 | return status; |
848 | } | 930 | } |
@@ -870,7 +952,8 @@ static int nfs_attribute_cache_expired(struct inode *inode) | |||
870 | */ | 952 | */ |
871 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 953 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
872 | { | 954 | { |
873 | if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR) | 955 | if (!(NFS_I(inode)->cache_validity & |
956 | (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) | ||
874 | && !nfs_attribute_cache_expired(inode)) | 957 | && !nfs_attribute_cache_expired(inode)) |
875 | return NFS_STALE(inode) ? -ESTALE : 0; | 958 | return NFS_STALE(inode) ? -ESTALE : 0; |
876 | return __nfs_revalidate_inode(server, inode); | 959 | return __nfs_revalidate_inode(server, inode); |
@@ -1250,6 +1333,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1250 | spin_lock(&inode->i_lock); | 1333 | spin_lock(&inode->i_lock); |
1251 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1334 | status = nfs_post_op_update_inode_locked(inode, fattr); |
1252 | spin_unlock(&inode->i_lock); | 1335 | spin_unlock(&inode->i_lock); |
1336 | |||
1253 | return status; | 1337 | return status; |
1254 | } | 1338 | } |
1255 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | 1339 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); |
@@ -1490,7 +1574,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1490 | inode->i_blocks = fattr->du.nfs2.blocks; | 1574 | inode->i_blocks = fattr->du.nfs2.blocks; |
1491 | 1575 | ||
1492 | /* Update attrtimeo value if we're out of the unstable period */ | 1576 | /* Update attrtimeo value if we're out of the unstable period */ |
1493 | if (invalid & NFS_INO_INVALID_ATTR) { | 1577 | if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) { |
1494 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1578 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
1495 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1579 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
1496 | nfsi->attrtimeo_timestamp = now; | 1580 | nfsi->attrtimeo_timestamp = now; |
@@ -1503,6 +1587,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1503 | } | 1587 | } |
1504 | } | 1588 | } |
1505 | invalid &= ~NFS_INO_INVALID_ATTR; | 1589 | invalid &= ~NFS_INO_INVALID_ATTR; |
1590 | invalid &= ~NFS_INO_INVALID_LABEL; | ||
1506 | /* Don't invalidate the data if we were to blame */ | 1591 | /* Don't invalidate the data if we were to blame */ |
1507 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1592 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
1508 | || S_ISLNK(inode->i_mode))) | 1593 | || S_ISLNK(inode->i_mode))) |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 4bd53f4e0fd2..3c8373f90ab3 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -165,7 +165,7 @@ extern void nfs_free_client(struct nfs_client *); | |||
165 | extern struct nfs_client *nfs4_find_client_ident(struct net *, int); | 165 | extern struct nfs_client *nfs4_find_client_ident(struct net *, int); |
166 | extern struct nfs_client * | 166 | extern struct nfs_client * |
167 | nfs4_find_client_sessionid(struct net *, const struct sockaddr *, | 167 | nfs4_find_client_sessionid(struct net *, const struct sockaddr *, |
168 | struct nfs4_sessionid *); | 168 | struct nfs4_sessionid *, u32); |
169 | extern struct nfs_server *nfs_create_server(struct nfs_mount_info *, | 169 | extern struct nfs_server *nfs_create_server(struct nfs_mount_info *, |
170 | struct nfs_subversion *); | 170 | struct nfs_subversion *); |
171 | extern struct nfs_server *nfs4_create_server( | 171 | extern struct nfs_server *nfs4_create_server( |
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index fc8dc20fdeb9..348b535cd786 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -280,7 +280,7 @@ struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry, | |||
280 | struct dentry *parent = dget_parent(dentry); | 280 | struct dentry *parent = dget_parent(dentry); |
281 | 281 | ||
282 | /* Look it up again to get its attributes */ | 282 | /* Look it up again to get its attributes */ |
283 | err = server->nfs_client->rpc_ops->lookup(parent->d_inode, &dentry->d_name, fh, fattr); | 283 | err = server->nfs_client->rpc_ops->lookup(parent->d_inode, &dentry->d_name, fh, fattr, NULL); |
284 | dput(parent); | 284 | dput(parent); |
285 | if (err != 0) | 285 | if (err != 0) |
286 | return ERR_PTR(err); | 286 | return ERR_PTR(err); |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 43ea96ced28c..39c185b03cc0 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -98,7 +98,7 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
98 | */ | 98 | */ |
99 | static int | 99 | static int |
100 | nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | 100 | nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, |
101 | struct nfs_fattr *fattr) | 101 | struct nfs_fattr *fattr, struct nfs4_label *label) |
102 | { | 102 | { |
103 | struct rpc_message msg = { | 103 | struct rpc_message msg = { |
104 | .rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR], | 104 | .rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR], |
@@ -143,7 +143,8 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
143 | 143 | ||
144 | static int | 144 | static int |
145 | nfs3_proc_lookup(struct inode *dir, struct qstr *name, | 145 | nfs3_proc_lookup(struct inode *dir, struct qstr *name, |
146 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 146 | struct nfs_fh *fhandle, struct nfs_fattr *fattr, |
147 | struct nfs4_label *label) | ||
147 | { | 148 | { |
148 | struct nfs3_diropargs arg = { | 149 | struct nfs3_diropargs arg = { |
149 | .fh = NFS_FH(dir), | 150 | .fh = NFS_FH(dir), |
@@ -300,7 +301,7 @@ static int nfs3_do_create(struct inode *dir, struct dentry *dentry, struct nfs3_ | |||
300 | status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0); | 301 | status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0); |
301 | nfs_post_op_update_inode(dir, data->res.dir_attr); | 302 | nfs_post_op_update_inode(dir, data->res.dir_attr); |
302 | if (status == 0) | 303 | if (status == 0) |
303 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 304 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); |
304 | return status; | 305 | return status; |
305 | } | 306 | } |
306 | 307 | ||
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index e64a00c03371..ee81e354bce7 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -303,10 +303,10 @@ is_ds_client(struct nfs_client *clp) | |||
303 | extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; | 303 | extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; |
304 | 304 | ||
305 | extern const u32 nfs4_fattr_bitmap[3]; | 305 | extern const u32 nfs4_fattr_bitmap[3]; |
306 | extern const u32 nfs4_statfs_bitmap[2]; | 306 | extern const u32 nfs4_statfs_bitmap[3]; |
307 | extern const u32 nfs4_pathconf_bitmap[2]; | 307 | extern const u32 nfs4_pathconf_bitmap[3]; |
308 | extern const u32 nfs4_fsinfo_bitmap[3]; | 308 | extern const u32 nfs4_fsinfo_bitmap[3]; |
309 | extern const u32 nfs4_fs_locations_bitmap[2]; | 309 | extern const u32 nfs4_fs_locations_bitmap[3]; |
310 | 310 | ||
311 | void nfs4_free_client(struct nfs_client *); | 311 | void nfs4_free_client(struct nfs_client *); |
312 | 312 | ||
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 0054e4bd6b55..90dce91dd5b5 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -66,6 +66,11 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) | |||
66 | if (err) | 66 | if (err) |
67 | goto error; | 67 | goto error; |
68 | 68 | ||
69 | if (cl_init->minorversion > NFS4_MAX_MINOR_VERSION) { | ||
70 | err = -EINVAL; | ||
71 | goto error; | ||
72 | } | ||
73 | |||
69 | spin_lock_init(&clp->cl_lock); | 74 | spin_lock_init(&clp->cl_lock); |
70 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); | 75 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); |
71 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); | 76 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); |
@@ -562,14 +567,14 @@ static bool nfs4_cb_match_client(const struct sockaddr *addr, | |||
562 | */ | 567 | */ |
563 | struct nfs_client * | 568 | struct nfs_client * |
564 | nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, | 569 | nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, |
565 | struct nfs4_sessionid *sid) | 570 | struct nfs4_sessionid *sid, u32 minorversion) |
566 | { | 571 | { |
567 | struct nfs_client *clp; | 572 | struct nfs_client *clp; |
568 | struct nfs_net *nn = net_generic(net, nfs_net_id); | 573 | struct nfs_net *nn = net_generic(net, nfs_net_id); |
569 | 574 | ||
570 | spin_lock(&nn->nfs_client_lock); | 575 | spin_lock(&nn->nfs_client_lock); |
571 | list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { | 576 | list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { |
572 | if (nfs4_cb_match_client(addr, clp, 1) == false) | 577 | if (nfs4_cb_match_client(addr, clp, minorversion) == false) |
573 | continue; | 578 | continue; |
574 | 579 | ||
575 | if (!nfs4_has_session(clp)) | 580 | if (!nfs4_has_session(clp)) |
@@ -592,7 +597,7 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, | |||
592 | 597 | ||
593 | struct nfs_client * | 598 | struct nfs_client * |
594 | nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, | 599 | nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, |
595 | struct nfs4_sessionid *sid) | 600 | struct nfs4_sessionid *sid, u32 minorversion) |
596 | { | 601 | { |
597 | return NULL; | 602 | return NULL; |
598 | } | 603 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 6d46f966d169..d95616f140ad 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -77,17 +77,68 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | |||
77 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 77 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
78 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); | 78 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); |
79 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); | 79 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); |
80 | static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *); | 80 | static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label); |
81 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 81 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label); |
82 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | 82 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, |
83 | struct nfs_fattr *fattr, struct iattr *sattr, | 83 | struct nfs_fattr *fattr, struct iattr *sattr, |
84 | struct nfs4_state *state); | 84 | struct nfs4_state *state, struct nfs4_label *ilabel, |
85 | struct nfs4_label *olabel); | ||
85 | #ifdef CONFIG_NFS_V4_1 | 86 | #ifdef CONFIG_NFS_V4_1 |
86 | static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *, | 87 | static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *, |
87 | struct rpc_cred *); | 88 | struct rpc_cred *); |
88 | static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *, | 89 | static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *, |
89 | struct rpc_cred *); | 90 | struct rpc_cred *); |
90 | #endif | 91 | #endif |
92 | |||
93 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
94 | static inline struct nfs4_label * | ||
95 | nfs4_label_init_security(struct inode *dir, struct dentry *dentry, | ||
96 | struct iattr *sattr, struct nfs4_label *label) | ||
97 | { | ||
98 | int err; | ||
99 | |||
100 | if (label == NULL) | ||
101 | return NULL; | ||
102 | |||
103 | if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0) | ||
104 | return NULL; | ||
105 | |||
106 | if (NFS_SERVER(dir)->nfs_client->cl_minorversion < 2) | ||
107 | return NULL; | ||
108 | |||
109 | err = security_dentry_init_security(dentry, sattr->ia_mode, | ||
110 | &dentry->d_name, (void **)&label->label, &label->len); | ||
111 | if (err == 0) | ||
112 | return label; | ||
113 | |||
114 | return NULL; | ||
115 | } | ||
116 | static inline void | ||
117 | nfs4_label_release_security(struct nfs4_label *label) | ||
118 | { | ||
119 | if (label) | ||
120 | security_release_secctx(label->label, label->len); | ||
121 | } | ||
122 | static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label) | ||
123 | { | ||
124 | if (label) | ||
125 | return server->attr_bitmask; | ||
126 | |||
127 | return server->attr_bitmask_nl; | ||
128 | } | ||
129 | #else | ||
130 | static inline struct nfs4_label * | ||
131 | nfs4_label_init_security(struct inode *dir, struct dentry *dentry, | ||
132 | struct iattr *sattr, struct nfs4_label *l) | ||
133 | { return NULL; } | ||
134 | static inline void | ||
135 | nfs4_label_release_security(struct nfs4_label *label) | ||
136 | { return; } | ||
137 | static inline u32 * | ||
138 | nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label) | ||
139 | { return server->attr_bitmask; } | ||
140 | #endif | ||
141 | |||
91 | /* Prevent leaks of NFSv4 errors into userland */ | 142 | /* Prevent leaks of NFSv4 errors into userland */ |
92 | static int nfs4_map_errors(int err) | 143 | static int nfs4_map_errors(int err) |
93 | { | 144 | { |
@@ -136,7 +187,10 @@ const u32 nfs4_fattr_bitmap[3] = { | |||
136 | | FATTR4_WORD1_SPACE_USED | 187 | | FATTR4_WORD1_SPACE_USED |
137 | | FATTR4_WORD1_TIME_ACCESS | 188 | | FATTR4_WORD1_TIME_ACCESS |
138 | | FATTR4_WORD1_TIME_METADATA | 189 | | FATTR4_WORD1_TIME_METADATA |
139 | | FATTR4_WORD1_TIME_MODIFY | 190 | | FATTR4_WORD1_TIME_MODIFY, |
191 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
192 | FATTR4_WORD2_SECURITY_LABEL | ||
193 | #endif | ||
140 | }; | 194 | }; |
141 | 195 | ||
142 | static const u32 nfs4_pnfs_open_bitmap[3] = { | 196 | static const u32 nfs4_pnfs_open_bitmap[3] = { |
@@ -163,7 +217,7 @@ static const u32 nfs4_open_noattr_bitmap[3] = { | |||
163 | | FATTR4_WORD0_FILEID, | 217 | | FATTR4_WORD0_FILEID, |
164 | }; | 218 | }; |
165 | 219 | ||
166 | const u32 nfs4_statfs_bitmap[2] = { | 220 | const u32 nfs4_statfs_bitmap[3] = { |
167 | FATTR4_WORD0_FILES_AVAIL | 221 | FATTR4_WORD0_FILES_AVAIL |
168 | | FATTR4_WORD0_FILES_FREE | 222 | | FATTR4_WORD0_FILES_FREE |
169 | | FATTR4_WORD0_FILES_TOTAL, | 223 | | FATTR4_WORD0_FILES_TOTAL, |
@@ -172,7 +226,7 @@ const u32 nfs4_statfs_bitmap[2] = { | |||
172 | | FATTR4_WORD1_SPACE_TOTAL | 226 | | FATTR4_WORD1_SPACE_TOTAL |
173 | }; | 227 | }; |
174 | 228 | ||
175 | const u32 nfs4_pathconf_bitmap[2] = { | 229 | const u32 nfs4_pathconf_bitmap[3] = { |
176 | FATTR4_WORD0_MAXLINK | 230 | FATTR4_WORD0_MAXLINK |
177 | | FATTR4_WORD0_MAXNAME, | 231 | | FATTR4_WORD0_MAXNAME, |
178 | 0 | 232 | 0 |
@@ -187,7 +241,7 @@ const u32 nfs4_fsinfo_bitmap[3] = { FATTR4_WORD0_MAXFILESIZE | |||
187 | FATTR4_WORD2_LAYOUT_BLKSIZE | 241 | FATTR4_WORD2_LAYOUT_BLKSIZE |
188 | }; | 242 | }; |
189 | 243 | ||
190 | const u32 nfs4_fs_locations_bitmap[2] = { | 244 | const u32 nfs4_fs_locations_bitmap[3] = { |
191 | FATTR4_WORD0_TYPE | 245 | FATTR4_WORD0_TYPE |
192 | | FATTR4_WORD0_CHANGE | 246 | | FATTR4_WORD0_CHANGE |
193 | | FATTR4_WORD0_SIZE | 247 | | FATTR4_WORD0_SIZE |
@@ -203,7 +257,7 @@ const u32 nfs4_fs_locations_bitmap[2] = { | |||
203 | | FATTR4_WORD1_TIME_ACCESS | 257 | | FATTR4_WORD1_TIME_ACCESS |
204 | | FATTR4_WORD1_TIME_METADATA | 258 | | FATTR4_WORD1_TIME_METADATA |
205 | | FATTR4_WORD1_TIME_MODIFY | 259 | | FATTR4_WORD1_TIME_MODIFY |
206 | | FATTR4_WORD1_MOUNTED_ON_FILEID | 260 | | FATTR4_WORD1_MOUNTED_ON_FILEID, |
207 | }; | 261 | }; |
208 | 262 | ||
209 | static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry, | 263 | static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry, |
@@ -764,6 +818,7 @@ struct nfs4_opendata { | |||
764 | struct nfs4_string owner_name; | 818 | struct nfs4_string owner_name; |
765 | struct nfs4_string group_name; | 819 | struct nfs4_string group_name; |
766 | struct nfs_fattr f_attr; | 820 | struct nfs_fattr f_attr; |
821 | struct nfs4_label *f_label; | ||
767 | struct dentry *dir; | 822 | struct dentry *dir; |
768 | struct dentry *dentry; | 823 | struct dentry *dentry; |
769 | struct nfs4_state_owner *owner; | 824 | struct nfs4_state_owner *owner; |
@@ -809,6 +864,7 @@ nfs4_map_atomic_open_claim(struct nfs_server *server, | |||
809 | static void nfs4_init_opendata_res(struct nfs4_opendata *p) | 864 | static void nfs4_init_opendata_res(struct nfs4_opendata *p) |
810 | { | 865 | { |
811 | p->o_res.f_attr = &p->f_attr; | 866 | p->o_res.f_attr = &p->f_attr; |
867 | p->o_res.f_label = p->f_label; | ||
812 | p->o_res.seqid = p->o_arg.seqid; | 868 | p->o_res.seqid = p->o_arg.seqid; |
813 | p->c_res.seqid = p->c_arg.seqid; | 869 | p->c_res.seqid = p->c_arg.seqid; |
814 | p->o_res.server = p->o_arg.server; | 870 | p->o_res.server = p->o_arg.server; |
@@ -820,6 +876,7 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p) | |||
820 | static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | 876 | static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, |
821 | struct nfs4_state_owner *sp, fmode_t fmode, int flags, | 877 | struct nfs4_state_owner *sp, fmode_t fmode, int flags, |
822 | const struct iattr *attrs, | 878 | const struct iattr *attrs, |
879 | struct nfs4_label *label, | ||
823 | enum open_claim_type4 claim, | 880 | enum open_claim_type4 claim, |
824 | gfp_t gfp_mask) | 881 | gfp_t gfp_mask) |
825 | { | 882 | { |
@@ -831,9 +888,14 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
831 | p = kzalloc(sizeof(*p), gfp_mask); | 888 | p = kzalloc(sizeof(*p), gfp_mask); |
832 | if (p == NULL) | 889 | if (p == NULL) |
833 | goto err; | 890 | goto err; |
891 | |||
892 | p->f_label = nfs4_label_alloc(server, gfp_mask); | ||
893 | if (IS_ERR(p->f_label)) | ||
894 | goto err_free_p; | ||
895 | |||
834 | p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask); | 896 | p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask); |
835 | if (p->o_arg.seqid == NULL) | 897 | if (p->o_arg.seqid == NULL) |
836 | goto err_free; | 898 | goto err_free_label; |
837 | nfs_sb_active(dentry->d_sb); | 899 | nfs_sb_active(dentry->d_sb); |
838 | p->dentry = dget(dentry); | 900 | p->dentry = dget(dentry); |
839 | p->dir = parent; | 901 | p->dir = parent; |
@@ -854,8 +916,9 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
854 | p->o_arg.id.uniquifier = sp->so_seqid.owner_id; | 916 | p->o_arg.id.uniquifier = sp->so_seqid.owner_id; |
855 | p->o_arg.name = &dentry->d_name; | 917 | p->o_arg.name = &dentry->d_name; |
856 | p->o_arg.server = server; | 918 | p->o_arg.server = server; |
857 | p->o_arg.bitmask = server->attr_bitmask; | 919 | p->o_arg.bitmask = nfs4_bitmask(server, label); |
858 | p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; | 920 | p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; |
921 | p->o_arg.label = label; | ||
859 | p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim); | 922 | p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim); |
860 | switch (p->o_arg.claim) { | 923 | switch (p->o_arg.claim) { |
861 | case NFS4_OPEN_CLAIM_NULL: | 924 | case NFS4_OPEN_CLAIM_NULL: |
@@ -886,7 +949,10 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
886 | nfs4_init_opendata_res(p); | 949 | nfs4_init_opendata_res(p); |
887 | kref_init(&p->kref); | 950 | kref_init(&p->kref); |
888 | return p; | 951 | return p; |
889 | err_free: | 952 | |
953 | err_free_label: | ||
954 | nfs4_label_free(p->f_label); | ||
955 | err_free_p: | ||
890 | kfree(p); | 956 | kfree(p); |
891 | err: | 957 | err: |
892 | dput(parent); | 958 | dput(parent); |
@@ -903,6 +969,9 @@ static void nfs4_opendata_free(struct kref *kref) | |||
903 | if (p->state != NULL) | 969 | if (p->state != NULL) |
904 | nfs4_put_open_state(p->state); | 970 | nfs4_put_open_state(p->state); |
905 | nfs4_put_state_owner(p->owner); | 971 | nfs4_put_state_owner(p->owner); |
972 | |||
973 | nfs4_label_free(p->f_label); | ||
974 | |||
906 | dput(p->dir); | 975 | dput(p->dir); |
907 | dput(p->dentry); | 976 | dput(p->dentry); |
908 | nfs_sb_deactive(sb); | 977 | nfs_sb_deactive(sb); |
@@ -1181,6 +1250,8 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) | |||
1181 | if (ret) | 1250 | if (ret) |
1182 | goto err; | 1251 | goto err; |
1183 | 1252 | ||
1253 | nfs_setsecurity(inode, &data->f_attr, data->f_label); | ||
1254 | |||
1184 | if (data->o_res.delegation_type != 0) | 1255 | if (data->o_res.delegation_type != 0) |
1185 | nfs4_opendata_check_deleg(data, state); | 1256 | nfs4_opendata_check_deleg(data, state); |
1186 | update_open_stateid(state, &data->o_res.stateid, NULL, | 1257 | update_open_stateid(state, &data->o_res.stateid, NULL, |
@@ -1207,7 +1278,7 @@ _nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data) | |||
1207 | ret = -EAGAIN; | 1278 | ret = -EAGAIN; |
1208 | if (!(data->f_attr.valid & NFS_ATTR_FATTR)) | 1279 | if (!(data->f_attr.valid & NFS_ATTR_FATTR)) |
1209 | goto err; | 1280 | goto err; |
1210 | inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr); | 1281 | inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr, data->f_label); |
1211 | ret = PTR_ERR(inode); | 1282 | ret = PTR_ERR(inode); |
1212 | if (IS_ERR(inode)) | 1283 | if (IS_ERR(inode)) |
1213 | goto err; | 1284 | goto err; |
@@ -1260,7 +1331,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context | |||
1260 | struct nfs4_opendata *opendata; | 1331 | struct nfs4_opendata *opendata; |
1261 | 1332 | ||
1262 | opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0, | 1333 | opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0, |
1263 | NULL, claim, GFP_NOFS); | 1334 | NULL, NULL, claim, GFP_NOFS); |
1264 | if (opendata == NULL) | 1335 | if (opendata == NULL) |
1265 | return ERR_PTR(-ENOMEM); | 1336 | return ERR_PTR(-ENOMEM); |
1266 | opendata->state = state; | 1337 | opendata->state = state; |
@@ -1786,7 +1857,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
1786 | return status; | 1857 | return status; |
1787 | } | 1858 | } |
1788 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) | 1859 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) |
1789 | _nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr); | 1860 | _nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, o_res->f_label); |
1790 | return 0; | 1861 | return 0; |
1791 | } | 1862 | } |
1792 | 1863 | ||
@@ -2017,7 +2088,8 @@ out: | |||
2017 | static int _nfs4_do_open(struct inode *dir, | 2088 | static int _nfs4_do_open(struct inode *dir, |
2018 | struct nfs_open_context *ctx, | 2089 | struct nfs_open_context *ctx, |
2019 | int flags, | 2090 | int flags, |
2020 | struct iattr *sattr) | 2091 | struct iattr *sattr, |
2092 | struct nfs4_label *label) | ||
2021 | { | 2093 | { |
2022 | struct nfs4_state_owner *sp; | 2094 | struct nfs4_state_owner *sp; |
2023 | struct nfs4_state *state = NULL; | 2095 | struct nfs4_state *state = NULL; |
@@ -2028,6 +2100,7 @@ static int _nfs4_do_open(struct inode *dir, | |||
2028 | struct nfs4_threshold **ctx_th = &ctx->mdsthreshold; | 2100 | struct nfs4_threshold **ctx_th = &ctx->mdsthreshold; |
2029 | fmode_t fmode = ctx->mode & (FMODE_READ|FMODE_WRITE|FMODE_EXEC); | 2101 | fmode_t fmode = ctx->mode & (FMODE_READ|FMODE_WRITE|FMODE_EXEC); |
2030 | enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL; | 2102 | enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL; |
2103 | struct nfs4_label *olabel = NULL; | ||
2031 | int status; | 2104 | int status; |
2032 | 2105 | ||
2033 | /* Protect against reboot recovery conflicts */ | 2106 | /* Protect against reboot recovery conflicts */ |
@@ -2046,14 +2119,22 @@ static int _nfs4_do_open(struct inode *dir, | |||
2046 | if (dentry->d_inode) | 2119 | if (dentry->d_inode) |
2047 | claim = NFS4_OPEN_CLAIM_FH; | 2120 | claim = NFS4_OPEN_CLAIM_FH; |
2048 | opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr, | 2121 | opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr, |
2049 | claim, GFP_KERNEL); | 2122 | label, claim, GFP_KERNEL); |
2050 | if (opendata == NULL) | 2123 | if (opendata == NULL) |
2051 | goto err_put_state_owner; | 2124 | goto err_put_state_owner; |
2052 | 2125 | ||
2126 | if (label) { | ||
2127 | olabel = nfs4_label_alloc(server, GFP_KERNEL); | ||
2128 | if (IS_ERR(olabel)) { | ||
2129 | status = PTR_ERR(olabel); | ||
2130 | goto err_opendata_put; | ||
2131 | } | ||
2132 | } | ||
2133 | |||
2053 | if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) { | 2134 | if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) { |
2054 | opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc(); | 2135 | opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc(); |
2055 | if (!opendata->f_attr.mdsthreshold) | 2136 | if (!opendata->f_attr.mdsthreshold) |
2056 | goto err_opendata_put; | 2137 | goto err_free_label; |
2057 | opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0]; | 2138 | opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0]; |
2058 | } | 2139 | } |
2059 | if (dentry->d_inode != NULL) | 2140 | if (dentry->d_inode != NULL) |
@@ -2061,7 +2142,7 @@ static int _nfs4_do_open(struct inode *dir, | |||
2061 | 2142 | ||
2062 | status = _nfs4_open_and_get_state(opendata, fmode, flags, ctx); | 2143 | status = _nfs4_open_and_get_state(opendata, fmode, flags, ctx); |
2063 | if (status != 0) | 2144 | if (status != 0) |
2064 | goto err_opendata_put; | 2145 | goto err_free_label; |
2065 | state = ctx->state; | 2146 | state = ctx->state; |
2066 | 2147 | ||
2067 | if ((opendata->o_arg.open_flags & O_EXCL) && | 2148 | if ((opendata->o_arg.open_flags & O_EXCL) && |
@@ -2071,10 +2152,12 @@ static int _nfs4_do_open(struct inode *dir, | |||
2071 | nfs_fattr_init(opendata->o_res.f_attr); | 2152 | nfs_fattr_init(opendata->o_res.f_attr); |
2072 | status = nfs4_do_setattr(state->inode, cred, | 2153 | status = nfs4_do_setattr(state->inode, cred, |
2073 | opendata->o_res.f_attr, sattr, | 2154 | opendata->o_res.f_attr, sattr, |
2074 | state); | 2155 | state, label, olabel); |
2075 | if (status == 0) | 2156 | if (status == 0) { |
2076 | nfs_setattr_update_inode(state->inode, sattr); | 2157 | nfs_setattr_update_inode(state->inode, sattr); |
2077 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); | 2158 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); |
2159 | nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel); | ||
2160 | } | ||
2078 | } | 2161 | } |
2079 | 2162 | ||
2080 | if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) | 2163 | if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) |
@@ -2083,9 +2166,13 @@ static int _nfs4_do_open(struct inode *dir, | |||
2083 | kfree(opendata->f_attr.mdsthreshold); | 2166 | kfree(opendata->f_attr.mdsthreshold); |
2084 | opendata->f_attr.mdsthreshold = NULL; | 2167 | opendata->f_attr.mdsthreshold = NULL; |
2085 | 2168 | ||
2169 | nfs4_label_free(olabel); | ||
2170 | |||
2086 | nfs4_opendata_put(opendata); | 2171 | nfs4_opendata_put(opendata); |
2087 | nfs4_put_state_owner(sp); | 2172 | nfs4_put_state_owner(sp); |
2088 | return 0; | 2173 | return 0; |
2174 | err_free_label: | ||
2175 | nfs4_label_free(olabel); | ||
2089 | err_opendata_put: | 2176 | err_opendata_put: |
2090 | kfree(opendata->f_attr.mdsthreshold); | 2177 | kfree(opendata->f_attr.mdsthreshold); |
2091 | nfs4_opendata_put(opendata); | 2178 | nfs4_opendata_put(opendata); |
@@ -2099,7 +2186,8 @@ out_err: | |||
2099 | static struct nfs4_state *nfs4_do_open(struct inode *dir, | 2186 | static struct nfs4_state *nfs4_do_open(struct inode *dir, |
2100 | struct nfs_open_context *ctx, | 2187 | struct nfs_open_context *ctx, |
2101 | int flags, | 2188 | int flags, |
2102 | struct iattr *sattr) | 2189 | struct iattr *sattr, |
2190 | struct nfs4_label *label) | ||
2103 | { | 2191 | { |
2104 | struct nfs_server *server = NFS_SERVER(dir); | 2192 | struct nfs_server *server = NFS_SERVER(dir); |
2105 | struct nfs4_exception exception = { }; | 2193 | struct nfs4_exception exception = { }; |
@@ -2107,7 +2195,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, | |||
2107 | int status; | 2195 | int status; |
2108 | 2196 | ||
2109 | do { | 2197 | do { |
2110 | status = _nfs4_do_open(dir, ctx, flags, sattr); | 2198 | status = _nfs4_do_open(dir, ctx, flags, sattr, label); |
2111 | res = ctx->state; | 2199 | res = ctx->state; |
2112 | if (status == 0) | 2200 | if (status == 0) |
2113 | break; | 2201 | break; |
@@ -2154,7 +2242,8 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, | |||
2154 | 2242 | ||
2155 | static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | 2243 | static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, |
2156 | struct nfs_fattr *fattr, struct iattr *sattr, | 2244 | struct nfs_fattr *fattr, struct iattr *sattr, |
2157 | struct nfs4_state *state) | 2245 | struct nfs4_state *state, struct nfs4_label *ilabel, |
2246 | struct nfs4_label *olabel) | ||
2158 | { | 2247 | { |
2159 | struct nfs_server *server = NFS_SERVER(inode); | 2248 | struct nfs_server *server = NFS_SERVER(inode); |
2160 | struct nfs_setattrargs arg = { | 2249 | struct nfs_setattrargs arg = { |
@@ -2162,9 +2251,11 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
2162 | .iap = sattr, | 2251 | .iap = sattr, |
2163 | .server = server, | 2252 | .server = server, |
2164 | .bitmask = server->attr_bitmask, | 2253 | .bitmask = server->attr_bitmask, |
2254 | .label = ilabel, | ||
2165 | }; | 2255 | }; |
2166 | struct nfs_setattrres res = { | 2256 | struct nfs_setattrres res = { |
2167 | .fattr = fattr, | 2257 | .fattr = fattr, |
2258 | .label = olabel, | ||
2168 | .server = server, | 2259 | .server = server, |
2169 | }; | 2260 | }; |
2170 | struct rpc_message msg = { | 2261 | struct rpc_message msg = { |
@@ -2178,6 +2269,10 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
2178 | bool truncate; | 2269 | bool truncate; |
2179 | int status; | 2270 | int status; |
2180 | 2271 | ||
2272 | arg.bitmask = nfs4_bitmask(server, ilabel); | ||
2273 | if (ilabel) | ||
2274 | arg.bitmask = nfs4_bitmask(server, olabel); | ||
2275 | |||
2181 | nfs_fattr_init(fattr); | 2276 | nfs_fattr_init(fattr); |
2182 | 2277 | ||
2183 | /* Servers should only apply open mode checks for file size changes */ | 2278 | /* Servers should only apply open mode checks for file size changes */ |
@@ -2204,7 +2299,8 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
2204 | 2299 | ||
2205 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | 2300 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, |
2206 | struct nfs_fattr *fattr, struct iattr *sattr, | 2301 | struct nfs_fattr *fattr, struct iattr *sattr, |
2207 | struct nfs4_state *state) | 2302 | struct nfs4_state *state, struct nfs4_label *ilabel, |
2303 | struct nfs4_label *olabel) | ||
2208 | { | 2304 | { |
2209 | struct nfs_server *server = NFS_SERVER(inode); | 2305 | struct nfs_server *server = NFS_SERVER(inode); |
2210 | struct nfs4_exception exception = { | 2306 | struct nfs4_exception exception = { |
@@ -2213,7 +2309,7 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
2213 | }; | 2309 | }; |
2214 | int err; | 2310 | int err; |
2215 | do { | 2311 | do { |
2216 | err = _nfs4_do_setattr(inode, cred, fattr, sattr, state); | 2312 | err = _nfs4_do_setattr(inode, cred, fattr, sattr, state, ilabel, olabel); |
2217 | switch (err) { | 2313 | switch (err) { |
2218 | case -NFS4ERR_OPENMODE: | 2314 | case -NFS4ERR_OPENMODE: |
2219 | if (!(sattr->ia_valid & ATTR_SIZE)) { | 2315 | if (!(sattr->ia_valid & ATTR_SIZE)) { |
@@ -2458,9 +2554,15 @@ static struct inode * | |||
2458 | nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr) | 2554 | nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr) |
2459 | { | 2555 | { |
2460 | struct nfs4_state *state; | 2556 | struct nfs4_state *state; |
2557 | struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL; | ||
2558 | |||
2559 | label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); | ||
2461 | 2560 | ||
2462 | /* Protect against concurrent sillydeletes */ | 2561 | /* Protect against concurrent sillydeletes */ |
2463 | state = nfs4_do_open(dir, ctx, open_flags, attr); | 2562 | state = nfs4_do_open(dir, ctx, open_flags, attr, label); |
2563 | |||
2564 | nfs4_label_release_security(label); | ||
2565 | |||
2464 | if (IS_ERR(state)) | 2566 | if (IS_ERR(state)) |
2465 | return ERR_CAST(state); | 2567 | return ERR_CAST(state); |
2466 | return state->inode; | 2568 | return state->inode; |
@@ -2519,7 +2621,17 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f | |||
2519 | server->caps |= NFS_CAP_CTIME; | 2621 | server->caps |= NFS_CAP_CTIME; |
2520 | if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY) | 2622 | if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY) |
2521 | server->caps |= NFS_CAP_MTIME; | 2623 | server->caps |= NFS_CAP_MTIME; |
2624 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
2625 | if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL) | ||
2626 | server->caps |= NFS_CAP_SECURITY_LABEL; | ||
2627 | #endif | ||
2628 | memcpy(server->attr_bitmask_nl, res.attr_bitmask, | ||
2629 | sizeof(server->attr_bitmask)); | ||
2522 | 2630 | ||
2631 | if (server->caps & NFS_CAP_SECURITY_LABEL) { | ||
2632 | server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL; | ||
2633 | res.attr_bitmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL; | ||
2634 | } | ||
2523 | memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask)); | 2635 | memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask)); |
2524 | server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE; | 2636 | server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE; |
2525 | server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; | 2637 | server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; |
@@ -2545,8 +2657,9 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) | |||
2545 | static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | 2657 | static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, |
2546 | struct nfs_fsinfo *info) | 2658 | struct nfs_fsinfo *info) |
2547 | { | 2659 | { |
2660 | u32 bitmask[3]; | ||
2548 | struct nfs4_lookup_root_arg args = { | 2661 | struct nfs4_lookup_root_arg args = { |
2549 | .bitmask = nfs4_fattr_bitmap, | 2662 | .bitmask = bitmask, |
2550 | }; | 2663 | }; |
2551 | struct nfs4_lookup_res res = { | 2664 | struct nfs4_lookup_res res = { |
2552 | .server = server, | 2665 | .server = server, |
@@ -2559,6 +2672,13 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2559 | .rpc_resp = &res, | 2672 | .rpc_resp = &res, |
2560 | }; | 2673 | }; |
2561 | 2674 | ||
2675 | bitmask[0] = nfs4_fattr_bitmap[0]; | ||
2676 | bitmask[1] = nfs4_fattr_bitmap[1]; | ||
2677 | /* | ||
2678 | * Process the label in the upcoming getfattr | ||
2679 | */ | ||
2680 | bitmask[2] = nfs4_fattr_bitmap[2] & ~FATTR4_WORD2_SECURITY_LABEL; | ||
2681 | |||
2562 | nfs_fattr_init(info->fattr); | 2682 | nfs_fattr_init(info->fattr); |
2563 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 2683 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
2564 | } | 2684 | } |
@@ -2678,6 +2798,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh, | |||
2678 | { | 2798 | { |
2679 | int error; | 2799 | int error; |
2680 | struct nfs_fattr *fattr = info->fattr; | 2800 | struct nfs_fattr *fattr = info->fattr; |
2801 | struct nfs4_label *label = NULL; | ||
2681 | 2802 | ||
2682 | error = nfs4_server_capabilities(server, mntfh); | 2803 | error = nfs4_server_capabilities(server, mntfh); |
2683 | if (error < 0) { | 2804 | if (error < 0) { |
@@ -2685,16 +2806,23 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh, | |||
2685 | return error; | 2806 | return error; |
2686 | } | 2807 | } |
2687 | 2808 | ||
2688 | error = nfs4_proc_getattr(server, mntfh, fattr); | 2809 | label = nfs4_label_alloc(server, GFP_KERNEL); |
2810 | if (IS_ERR(label)) | ||
2811 | return PTR_ERR(label); | ||
2812 | |||
2813 | error = nfs4_proc_getattr(server, mntfh, fattr, label); | ||
2689 | if (error < 0) { | 2814 | if (error < 0) { |
2690 | dprintk("nfs4_get_root: getattr error = %d\n", -error); | 2815 | dprintk("nfs4_get_root: getattr error = %d\n", -error); |
2691 | return error; | 2816 | goto err_free_label; |
2692 | } | 2817 | } |
2693 | 2818 | ||
2694 | if (fattr->valid & NFS_ATTR_FATTR_FSID && | 2819 | if (fattr->valid & NFS_ATTR_FATTR_FSID && |
2695 | !nfs_fsid_equal(&server->fsid, &fattr->fsid)) | 2820 | !nfs_fsid_equal(&server->fsid, &fattr->fsid)) |
2696 | memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); | 2821 | memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); |
2697 | 2822 | ||
2823 | err_free_label: | ||
2824 | nfs4_label_free(label); | ||
2825 | |||
2698 | return error; | 2826 | return error; |
2699 | } | 2827 | } |
2700 | 2828 | ||
@@ -2741,7 +2869,8 @@ out: | |||
2741 | return status; | 2869 | return status; |
2742 | } | 2870 | } |
2743 | 2871 | ||
2744 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2872 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, |
2873 | struct nfs_fattr *fattr, struct nfs4_label *label) | ||
2745 | { | 2874 | { |
2746 | struct nfs4_getattr_arg args = { | 2875 | struct nfs4_getattr_arg args = { |
2747 | .fh = fhandle, | 2876 | .fh = fhandle, |
@@ -2749,6 +2878,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2749 | }; | 2878 | }; |
2750 | struct nfs4_getattr_res res = { | 2879 | struct nfs4_getattr_res res = { |
2751 | .fattr = fattr, | 2880 | .fattr = fattr, |
2881 | .label = label, | ||
2752 | .server = server, | 2882 | .server = server, |
2753 | }; | 2883 | }; |
2754 | struct rpc_message msg = { | 2884 | struct rpc_message msg = { |
@@ -2756,18 +2886,21 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2756 | .rpc_argp = &args, | 2886 | .rpc_argp = &args, |
2757 | .rpc_resp = &res, | 2887 | .rpc_resp = &res, |
2758 | }; | 2888 | }; |
2759 | 2889 | ||
2890 | args.bitmask = nfs4_bitmask(server, label); | ||
2891 | |||
2760 | nfs_fattr_init(fattr); | 2892 | nfs_fattr_init(fattr); |
2761 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 2893 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
2762 | } | 2894 | } |
2763 | 2895 | ||
2764 | static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2896 | static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, |
2897 | struct nfs_fattr *fattr, struct nfs4_label *label) | ||
2765 | { | 2898 | { |
2766 | struct nfs4_exception exception = { }; | 2899 | struct nfs4_exception exception = { }; |
2767 | int err; | 2900 | int err; |
2768 | do { | 2901 | do { |
2769 | err = nfs4_handle_exception(server, | 2902 | err = nfs4_handle_exception(server, |
2770 | _nfs4_proc_getattr(server, fhandle, fattr), | 2903 | _nfs4_proc_getattr(server, fhandle, fattr, label), |
2771 | &exception); | 2904 | &exception); |
2772 | } while (exception.retry); | 2905 | } while (exception.retry); |
2773 | return err; | 2906 | return err; |
@@ -2797,6 +2930,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
2797 | struct inode *inode = dentry->d_inode; | 2930 | struct inode *inode = dentry->d_inode; |
2798 | struct rpc_cred *cred = NULL; | 2931 | struct rpc_cred *cred = NULL; |
2799 | struct nfs4_state *state = NULL; | 2932 | struct nfs4_state *state = NULL; |
2933 | struct nfs4_label *label = NULL; | ||
2800 | int status; | 2934 | int status; |
2801 | 2935 | ||
2802 | if (pnfs_ld_layoutret_on_setattr(inode)) | 2936 | if (pnfs_ld_layoutret_on_setattr(inode)) |
@@ -2823,15 +2957,22 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
2823 | } | 2957 | } |
2824 | } | 2958 | } |
2825 | 2959 | ||
2826 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state); | 2960 | label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL); |
2827 | if (status == 0) | 2961 | if (IS_ERR(label)) |
2962 | return PTR_ERR(label); | ||
2963 | |||
2964 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label); | ||
2965 | if (status == 0) { | ||
2828 | nfs_setattr_update_inode(inode, sattr); | 2966 | nfs_setattr_update_inode(inode, sattr); |
2967 | nfs_setsecurity(inode, fattr, label); | ||
2968 | } | ||
2969 | nfs4_label_free(label); | ||
2829 | return status; | 2970 | return status; |
2830 | } | 2971 | } |
2831 | 2972 | ||
2832 | static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, | 2973 | static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, |
2833 | const struct qstr *name, struct nfs_fh *fhandle, | 2974 | const struct qstr *name, struct nfs_fh *fhandle, |
2834 | struct nfs_fattr *fattr) | 2975 | struct nfs_fattr *fattr, struct nfs4_label *label) |
2835 | { | 2976 | { |
2836 | struct nfs_server *server = NFS_SERVER(dir); | 2977 | struct nfs_server *server = NFS_SERVER(dir); |
2837 | int status; | 2978 | int status; |
@@ -2843,6 +2984,7 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, | |||
2843 | struct nfs4_lookup_res res = { | 2984 | struct nfs4_lookup_res res = { |
2844 | .server = server, | 2985 | .server = server, |
2845 | .fattr = fattr, | 2986 | .fattr = fattr, |
2987 | .label = label, | ||
2846 | .fh = fhandle, | 2988 | .fh = fhandle, |
2847 | }; | 2989 | }; |
2848 | struct rpc_message msg = { | 2990 | struct rpc_message msg = { |
@@ -2851,6 +2993,8 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, | |||
2851 | .rpc_resp = &res, | 2993 | .rpc_resp = &res, |
2852 | }; | 2994 | }; |
2853 | 2995 | ||
2996 | args.bitmask = nfs4_bitmask(server, label); | ||
2997 | |||
2854 | nfs_fattr_init(fattr); | 2998 | nfs_fattr_init(fattr); |
2855 | 2999 | ||
2856 | dprintk("NFS call lookup %s\n", name->name); | 3000 | dprintk("NFS call lookup %s\n", name->name); |
@@ -2869,13 +3013,13 @@ static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr) | |||
2869 | 3013 | ||
2870 | static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, | 3014 | static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, |
2871 | struct qstr *name, struct nfs_fh *fhandle, | 3015 | struct qstr *name, struct nfs_fh *fhandle, |
2872 | struct nfs_fattr *fattr) | 3016 | struct nfs_fattr *fattr, struct nfs4_label *label) |
2873 | { | 3017 | { |
2874 | struct nfs4_exception exception = { }; | 3018 | struct nfs4_exception exception = { }; |
2875 | struct rpc_clnt *client = *clnt; | 3019 | struct rpc_clnt *client = *clnt; |
2876 | int err; | 3020 | int err; |
2877 | do { | 3021 | do { |
2878 | err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr); | 3022 | err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr, label); |
2879 | switch (err) { | 3023 | switch (err) { |
2880 | case -NFS4ERR_BADNAME: | 3024 | case -NFS4ERR_BADNAME: |
2881 | err = -ENOENT; | 3025 | err = -ENOENT; |
@@ -2909,12 +3053,13 @@ out: | |||
2909 | } | 3053 | } |
2910 | 3054 | ||
2911 | static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, | 3055 | static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, |
2912 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 3056 | struct nfs_fh *fhandle, struct nfs_fattr *fattr, |
3057 | struct nfs4_label *label) | ||
2913 | { | 3058 | { |
2914 | int status; | 3059 | int status; |
2915 | struct rpc_clnt *client = NFS_CLIENT(dir); | 3060 | struct rpc_clnt *client = NFS_CLIENT(dir); |
2916 | 3061 | ||
2917 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr); | 3062 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, label); |
2918 | if (client != NFS_CLIENT(dir)) { | 3063 | if (client != NFS_CLIENT(dir)) { |
2919 | rpc_shutdown_client(client); | 3064 | rpc_shutdown_client(client); |
2920 | nfs_fixup_secinfo_attributes(fattr); | 3065 | nfs_fixup_secinfo_attributes(fattr); |
@@ -2929,7 +3074,7 @@ nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name, | |||
2929 | int status; | 3074 | int status; |
2930 | struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir)); | 3075 | struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir)); |
2931 | 3076 | ||
2932 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr); | 3077 | status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, NULL); |
2933 | if (status < 0) { | 3078 | if (status < 0) { |
2934 | rpc_shutdown_client(client); | 3079 | rpc_shutdown_client(client); |
2935 | return ERR_PTR(status); | 3080 | return ERR_PTR(status); |
@@ -2954,7 +3099,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
2954 | .rpc_cred = entry->cred, | 3099 | .rpc_cred = entry->cred, |
2955 | }; | 3100 | }; |
2956 | int mode = entry->mask; | 3101 | int mode = entry->mask; |
2957 | int status; | 3102 | int status = 0; |
2958 | 3103 | ||
2959 | /* | 3104 | /* |
2960 | * Determine which access bits we want to ask for... | 3105 | * Determine which access bits we want to ask for... |
@@ -3059,6 +3204,7 @@ static int | |||
3059 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 3204 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
3060 | int flags) | 3205 | int flags) |
3061 | { | 3206 | { |
3207 | struct nfs4_label l, *ilabel = NULL; | ||
3062 | struct nfs_open_context *ctx; | 3208 | struct nfs_open_context *ctx; |
3063 | struct nfs4_state *state; | 3209 | struct nfs4_state *state; |
3064 | int status = 0; | 3210 | int status = 0; |
@@ -3067,13 +3213,16 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
3067 | if (IS_ERR(ctx)) | 3213 | if (IS_ERR(ctx)) |
3068 | return PTR_ERR(ctx); | 3214 | return PTR_ERR(ctx); |
3069 | 3215 | ||
3216 | ilabel = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3217 | |||
3070 | sattr->ia_mode &= ~current_umask(); | 3218 | sattr->ia_mode &= ~current_umask(); |
3071 | state = nfs4_do_open(dir, ctx, flags, sattr); | 3219 | state = nfs4_do_open(dir, ctx, flags, sattr, ilabel); |
3072 | if (IS_ERR(state)) { | 3220 | if (IS_ERR(state)) { |
3073 | status = PTR_ERR(state); | 3221 | status = PTR_ERR(state); |
3074 | goto out; | 3222 | goto out; |
3075 | } | 3223 | } |
3076 | out: | 3224 | out: |
3225 | nfs4_label_release_security(ilabel); | ||
3077 | put_nfs_open_context(ctx); | 3226 | put_nfs_open_context(ctx); |
3078 | return status; | 3227 | return status; |
3079 | } | 3228 | } |
@@ -3122,6 +3271,8 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
3122 | res->server = server; | 3271 | res->server = server; |
3123 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 3272 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
3124 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); | 3273 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); |
3274 | |||
3275 | nfs_fattr_init(res->dir_attr); | ||
3125 | } | 3276 | } |
3126 | 3277 | ||
3127 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) | 3278 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) |
@@ -3197,7 +3348,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
3197 | .rpc_resp = &res, | 3348 | .rpc_resp = &res, |
3198 | }; | 3349 | }; |
3199 | int status = -ENOMEM; | 3350 | int status = -ENOMEM; |
3200 | 3351 | ||
3201 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 3352 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
3202 | if (!status) { | 3353 | if (!status) { |
3203 | update_changeattr(old_dir, &res.old_cinfo); | 3354 | update_changeattr(old_dir, &res.old_cinfo); |
@@ -3231,6 +3382,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
3231 | }; | 3382 | }; |
3232 | struct nfs4_link_res res = { | 3383 | struct nfs4_link_res res = { |
3233 | .server = server, | 3384 | .server = server, |
3385 | .label = NULL, | ||
3234 | }; | 3386 | }; |
3235 | struct rpc_message msg = { | 3387 | struct rpc_message msg = { |
3236 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], | 3388 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], |
@@ -3243,11 +3395,24 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
3243 | if (res.fattr == NULL) | 3395 | if (res.fattr == NULL) |
3244 | goto out; | 3396 | goto out; |
3245 | 3397 | ||
3398 | res.label = nfs4_label_alloc(server, GFP_KERNEL); | ||
3399 | if (IS_ERR(res.label)) { | ||
3400 | status = PTR_ERR(res.label); | ||
3401 | goto out; | ||
3402 | } | ||
3403 | arg.bitmask = nfs4_bitmask(server, res.label); | ||
3404 | |||
3246 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 3405 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
3247 | if (!status) { | 3406 | if (!status) { |
3248 | update_changeattr(dir, &res.cinfo); | 3407 | update_changeattr(dir, &res.cinfo); |
3249 | nfs_post_op_update_inode(inode, res.fattr); | 3408 | status = nfs_post_op_update_inode(inode, res.fattr); |
3409 | if (!status) | ||
3410 | nfs_setsecurity(inode, res.fattr, res.label); | ||
3250 | } | 3411 | } |
3412 | |||
3413 | |||
3414 | nfs4_label_free(res.label); | ||
3415 | |||
3251 | out: | 3416 | out: |
3252 | nfs_free_fattr(res.fattr); | 3417 | nfs_free_fattr(res.fattr); |
3253 | return status; | 3418 | return status; |
@@ -3271,6 +3436,7 @@ struct nfs4_createdata { | |||
3271 | struct nfs4_create_res res; | 3436 | struct nfs4_create_res res; |
3272 | struct nfs_fh fh; | 3437 | struct nfs_fh fh; |
3273 | struct nfs_fattr fattr; | 3438 | struct nfs_fattr fattr; |
3439 | struct nfs4_label *label; | ||
3274 | }; | 3440 | }; |
3275 | 3441 | ||
3276 | static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | 3442 | static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, |
@@ -3282,6 +3448,10 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | |||
3282 | if (data != NULL) { | 3448 | if (data != NULL) { |
3283 | struct nfs_server *server = NFS_SERVER(dir); | 3449 | struct nfs_server *server = NFS_SERVER(dir); |
3284 | 3450 | ||
3451 | data->label = nfs4_label_alloc(server, GFP_KERNEL); | ||
3452 | if (IS_ERR(data->label)) | ||
3453 | goto out_free; | ||
3454 | |||
3285 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE]; | 3455 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE]; |
3286 | data->msg.rpc_argp = &data->arg; | 3456 | data->msg.rpc_argp = &data->arg; |
3287 | data->msg.rpc_resp = &data->res; | 3457 | data->msg.rpc_resp = &data->res; |
@@ -3290,13 +3460,17 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | |||
3290 | data->arg.name = name; | 3460 | data->arg.name = name; |
3291 | data->arg.attrs = sattr; | 3461 | data->arg.attrs = sattr; |
3292 | data->arg.ftype = ftype; | 3462 | data->arg.ftype = ftype; |
3293 | data->arg.bitmask = server->attr_bitmask; | 3463 | data->arg.bitmask = nfs4_bitmask(server, data->label); |
3294 | data->res.server = server; | 3464 | data->res.server = server; |
3295 | data->res.fh = &data->fh; | 3465 | data->res.fh = &data->fh; |
3296 | data->res.fattr = &data->fattr; | 3466 | data->res.fattr = &data->fattr; |
3467 | data->res.label = data->label; | ||
3297 | nfs_fattr_init(data->res.fattr); | 3468 | nfs_fattr_init(data->res.fattr); |
3298 | } | 3469 | } |
3299 | return data; | 3470 | return data; |
3471 | out_free: | ||
3472 | kfree(data); | ||
3473 | return NULL; | ||
3300 | } | 3474 | } |
3301 | 3475 | ||
3302 | static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) | 3476 | static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) |
@@ -3305,18 +3479,20 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_ | |||
3305 | &data->arg.seq_args, &data->res.seq_res, 1); | 3479 | &data->arg.seq_args, &data->res.seq_res, 1); |
3306 | if (status == 0) { | 3480 | if (status == 0) { |
3307 | update_changeattr(dir, &data->res.dir_cinfo); | 3481 | update_changeattr(dir, &data->res.dir_cinfo); |
3308 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 3482 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label); |
3309 | } | 3483 | } |
3310 | return status; | 3484 | return status; |
3311 | } | 3485 | } |
3312 | 3486 | ||
3313 | static void nfs4_free_createdata(struct nfs4_createdata *data) | 3487 | static void nfs4_free_createdata(struct nfs4_createdata *data) |
3314 | { | 3488 | { |
3489 | nfs4_label_free(data->label); | ||
3315 | kfree(data); | 3490 | kfree(data); |
3316 | } | 3491 | } |
3317 | 3492 | ||
3318 | static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | 3493 | static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, |
3319 | struct page *page, unsigned int len, struct iattr *sattr) | 3494 | struct page *page, unsigned int len, struct iattr *sattr, |
3495 | struct nfs4_label *label) | ||
3320 | { | 3496 | { |
3321 | struct nfs4_createdata *data; | 3497 | struct nfs4_createdata *data; |
3322 | int status = -ENAMETOOLONG; | 3498 | int status = -ENAMETOOLONG; |
@@ -3332,6 +3508,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | |||
3332 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK]; | 3508 | data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK]; |
3333 | data->arg.u.symlink.pages = &page; | 3509 | data->arg.u.symlink.pages = &page; |
3334 | data->arg.u.symlink.len = len; | 3510 | data->arg.u.symlink.len = len; |
3511 | data->arg.label = label; | ||
3335 | 3512 | ||
3336 | status = nfs4_do_create(dir, dentry, data); | 3513 | status = nfs4_do_create(dir, dentry, data); |
3337 | 3514 | ||
@@ -3344,18 +3521,24 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | |||
3344 | struct page *page, unsigned int len, struct iattr *sattr) | 3521 | struct page *page, unsigned int len, struct iattr *sattr) |
3345 | { | 3522 | { |
3346 | struct nfs4_exception exception = { }; | 3523 | struct nfs4_exception exception = { }; |
3524 | struct nfs4_label l, *label = NULL; | ||
3347 | int err; | 3525 | int err; |
3526 | |||
3527 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3528 | |||
3348 | do { | 3529 | do { |
3349 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3530 | err = nfs4_handle_exception(NFS_SERVER(dir), |
3350 | _nfs4_proc_symlink(dir, dentry, page, | 3531 | _nfs4_proc_symlink(dir, dentry, page, |
3351 | len, sattr), | 3532 | len, sattr, label), |
3352 | &exception); | 3533 | &exception); |
3353 | } while (exception.retry); | 3534 | } while (exception.retry); |
3535 | |||
3536 | nfs4_label_release_security(label); | ||
3354 | return err; | 3537 | return err; |
3355 | } | 3538 | } |
3356 | 3539 | ||
3357 | static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | 3540 | static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, |
3358 | struct iattr *sattr) | 3541 | struct iattr *sattr, struct nfs4_label *label) |
3359 | { | 3542 | { |
3360 | struct nfs4_createdata *data; | 3543 | struct nfs4_createdata *data; |
3361 | int status = -ENOMEM; | 3544 | int status = -ENOMEM; |
@@ -3364,6 +3547,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
3364 | if (data == NULL) | 3547 | if (data == NULL) |
3365 | goto out; | 3548 | goto out; |
3366 | 3549 | ||
3550 | data->arg.label = label; | ||
3367 | status = nfs4_do_create(dir, dentry, data); | 3551 | status = nfs4_do_create(dir, dentry, data); |
3368 | 3552 | ||
3369 | nfs4_free_createdata(data); | 3553 | nfs4_free_createdata(data); |
@@ -3375,14 +3559,19 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
3375 | struct iattr *sattr) | 3559 | struct iattr *sattr) |
3376 | { | 3560 | { |
3377 | struct nfs4_exception exception = { }; | 3561 | struct nfs4_exception exception = { }; |
3562 | struct nfs4_label l, *label = NULL; | ||
3378 | int err; | 3563 | int err; |
3379 | 3564 | ||
3565 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3566 | |||
3380 | sattr->ia_mode &= ~current_umask(); | 3567 | sattr->ia_mode &= ~current_umask(); |
3381 | do { | 3568 | do { |
3382 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3569 | err = nfs4_handle_exception(NFS_SERVER(dir), |
3383 | _nfs4_proc_mkdir(dir, dentry, sattr), | 3570 | _nfs4_proc_mkdir(dir, dentry, sattr, label), |
3384 | &exception); | 3571 | &exception); |
3385 | } while (exception.retry); | 3572 | } while (exception.retry); |
3573 | nfs4_label_release_security(label); | ||
3574 | |||
3386 | return err; | 3575 | return err; |
3387 | } | 3576 | } |
3388 | 3577 | ||
@@ -3440,7 +3629,7 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
3440 | } | 3629 | } |
3441 | 3630 | ||
3442 | static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | 3631 | static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, |
3443 | struct iattr *sattr, dev_t rdev) | 3632 | struct iattr *sattr, struct nfs4_label *label, dev_t rdev) |
3444 | { | 3633 | { |
3445 | struct nfs4_createdata *data; | 3634 | struct nfs4_createdata *data; |
3446 | int mode = sattr->ia_mode; | 3635 | int mode = sattr->ia_mode; |
@@ -3465,7 +3654,8 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3465 | status = -EINVAL; | 3654 | status = -EINVAL; |
3466 | goto out_free; | 3655 | goto out_free; |
3467 | } | 3656 | } |
3468 | 3657 | ||
3658 | data->arg.label = label; | ||
3469 | status = nfs4_do_create(dir, dentry, data); | 3659 | status = nfs4_do_create(dir, dentry, data); |
3470 | out_free: | 3660 | out_free: |
3471 | nfs4_free_createdata(data); | 3661 | nfs4_free_createdata(data); |
@@ -3477,14 +3667,20 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3477 | struct iattr *sattr, dev_t rdev) | 3667 | struct iattr *sattr, dev_t rdev) |
3478 | { | 3668 | { |
3479 | struct nfs4_exception exception = { }; | 3669 | struct nfs4_exception exception = { }; |
3670 | struct nfs4_label l, *label = NULL; | ||
3480 | int err; | 3671 | int err; |
3481 | 3672 | ||
3673 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3674 | |||
3482 | sattr->ia_mode &= ~current_umask(); | 3675 | sattr->ia_mode &= ~current_umask(); |
3483 | do { | 3676 | do { |
3484 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3677 | err = nfs4_handle_exception(NFS_SERVER(dir), |
3485 | _nfs4_proc_mknod(dir, dentry, sattr, rdev), | 3678 | _nfs4_proc_mknod(dir, dentry, sattr, label, rdev), |
3486 | &exception); | 3679 | &exception); |
3487 | } while (exception.retry); | 3680 | } while (exception.retry); |
3681 | |||
3682 | nfs4_label_release_security(label); | ||
3683 | |||
3488 | return err; | 3684 | return err; |
3489 | } | 3685 | } |
3490 | 3686 | ||
@@ -4211,6 +4407,155 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
4211 | return err; | 4407 | return err; |
4212 | } | 4408 | } |
4213 | 4409 | ||
4410 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
4411 | static int _nfs4_get_security_label(struct inode *inode, void *buf, | ||
4412 | size_t buflen) | ||
4413 | { | ||
4414 | struct nfs_server *server = NFS_SERVER(inode); | ||
4415 | struct nfs_fattr fattr; | ||
4416 | struct nfs4_label label = {0, 0, buflen, buf}; | ||
4417 | |||
4418 | u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL }; | ||
4419 | struct nfs4_getattr_arg args = { | ||
4420 | .fh = NFS_FH(inode), | ||
4421 | .bitmask = bitmask, | ||
4422 | }; | ||
4423 | struct nfs4_getattr_res res = { | ||
4424 | .fattr = &fattr, | ||
4425 | .label = &label, | ||
4426 | .server = server, | ||
4427 | }; | ||
4428 | struct rpc_message msg = { | ||
4429 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR], | ||
4430 | .rpc_argp = &args, | ||
4431 | .rpc_resp = &res, | ||
4432 | }; | ||
4433 | int ret; | ||
4434 | |||
4435 | nfs_fattr_init(&fattr); | ||
4436 | |||
4437 | ret = rpc_call_sync(server->client, &msg, 0); | ||
4438 | if (ret) | ||
4439 | return ret; | ||
4440 | if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL)) | ||
4441 | return -ENOENT; | ||
4442 | if (buflen < label.len) | ||
4443 | return -ERANGE; | ||
4444 | return 0; | ||
4445 | } | ||
4446 | |||
4447 | static int nfs4_get_security_label(struct inode *inode, void *buf, | ||
4448 | size_t buflen) | ||
4449 | { | ||
4450 | struct nfs4_exception exception = { }; | ||
4451 | int err; | ||
4452 | |||
4453 | if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) | ||
4454 | return -EOPNOTSUPP; | ||
4455 | |||
4456 | do { | ||
4457 | err = nfs4_handle_exception(NFS_SERVER(inode), | ||
4458 | _nfs4_get_security_label(inode, buf, buflen), | ||
4459 | &exception); | ||
4460 | } while (exception.retry); | ||
4461 | return err; | ||
4462 | } | ||
4463 | |||
4464 | static int _nfs4_do_set_security_label(struct inode *inode, | ||
4465 | struct nfs4_label *ilabel, | ||
4466 | struct nfs_fattr *fattr, | ||
4467 | struct nfs4_label *olabel) | ||
4468 | { | ||
4469 | |||
4470 | struct iattr sattr = {0}; | ||
4471 | struct nfs_server *server = NFS_SERVER(inode); | ||
4472 | const u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL }; | ||
4473 | struct nfs_setattrargs args = { | ||
4474 | .fh = NFS_FH(inode), | ||
4475 | .iap = &sattr, | ||
4476 | .server = server, | ||
4477 | .bitmask = bitmask, | ||
4478 | .label = ilabel, | ||
4479 | }; | ||
4480 | struct nfs_setattrres res = { | ||
4481 | .fattr = fattr, | ||
4482 | .label = olabel, | ||
4483 | .server = server, | ||
4484 | }; | ||
4485 | struct rpc_message msg = { | ||
4486 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR], | ||
4487 | .rpc_argp = &args, | ||
4488 | .rpc_resp = &res, | ||
4489 | }; | ||
4490 | int status; | ||
4491 | |||
4492 | nfs4_stateid_copy(&args.stateid, &zero_stateid); | ||
4493 | |||
4494 | status = rpc_call_sync(server->client, &msg, 0); | ||
4495 | if (status) | ||
4496 | dprintk("%s failed: %d\n", __func__, status); | ||
4497 | |||
4498 | return status; | ||
4499 | } | ||
4500 | |||
4501 | static int nfs4_do_set_security_label(struct inode *inode, | ||
4502 | struct nfs4_label *ilabel, | ||
4503 | struct nfs_fattr *fattr, | ||
4504 | struct nfs4_label *olabel) | ||
4505 | { | ||
4506 | struct nfs4_exception exception = { }; | ||
4507 | int err; | ||
4508 | |||
4509 | do { | ||
4510 | err = nfs4_handle_exception(NFS_SERVER(inode), | ||
4511 | _nfs4_do_set_security_label(inode, ilabel, | ||
4512 | fattr, olabel), | ||
4513 | &exception); | ||
4514 | } while (exception.retry); | ||
4515 | return err; | ||
4516 | } | ||
4517 | |||
4518 | static int | ||
4519 | nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen) | ||
4520 | { | ||
4521 | struct nfs4_label ilabel, *olabel = NULL; | ||
4522 | struct nfs_fattr fattr; | ||
4523 | struct rpc_cred *cred; | ||
4524 | struct inode *inode = dentry->d_inode; | ||
4525 | int status; | ||
4526 | |||
4527 | if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) | ||
4528 | return -EOPNOTSUPP; | ||
4529 | |||
4530 | nfs_fattr_init(&fattr); | ||
4531 | |||
4532 | ilabel.pi = 0; | ||
4533 | ilabel.lfs = 0; | ||
4534 | ilabel.label = (char *)buf; | ||
4535 | ilabel.len = buflen; | ||
4536 | |||
4537 | cred = rpc_lookup_cred(); | ||
4538 | if (IS_ERR(cred)) | ||
4539 | return PTR_ERR(cred); | ||
4540 | |||
4541 | olabel = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL); | ||
4542 | if (IS_ERR(olabel)) { | ||
4543 | status = -PTR_ERR(olabel); | ||
4544 | goto out; | ||
4545 | } | ||
4546 | |||
4547 | status = nfs4_do_set_security_label(inode, &ilabel, &fattr, olabel); | ||
4548 | if (status == 0) | ||
4549 | nfs_setsecurity(inode, &fattr, olabel); | ||
4550 | |||
4551 | nfs4_label_free(olabel); | ||
4552 | out: | ||
4553 | put_rpccred(cred); | ||
4554 | return status; | ||
4555 | } | ||
4556 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ | ||
4557 | |||
4558 | |||
4214 | static int | 4559 | static int |
4215 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) | 4560 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) |
4216 | { | 4561 | { |
@@ -5324,6 +5669,53 @@ static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list, | |||
5324 | return len; | 5669 | return len; |
5325 | } | 5670 | } |
5326 | 5671 | ||
5672 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
5673 | static inline int nfs4_server_supports_labels(struct nfs_server *server) | ||
5674 | { | ||
5675 | return server->caps & NFS_CAP_SECURITY_LABEL; | ||
5676 | } | ||
5677 | |||
5678 | static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key, | ||
5679 | const void *buf, size_t buflen, | ||
5680 | int flags, int type) | ||
5681 | { | ||
5682 | if (security_ismaclabel(key)) | ||
5683 | return nfs4_set_security_label(dentry, buf, buflen); | ||
5684 | |||
5685 | return -EOPNOTSUPP; | ||
5686 | } | ||
5687 | |||
5688 | static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key, | ||
5689 | void *buf, size_t buflen, int type) | ||
5690 | { | ||
5691 | if (security_ismaclabel(key)) | ||
5692 | return nfs4_get_security_label(dentry->d_inode, buf, buflen); | ||
5693 | return -EOPNOTSUPP; | ||
5694 | } | ||
5695 | |||
5696 | static size_t nfs4_xattr_list_nfs4_label(struct dentry *dentry, char *list, | ||
5697 | size_t list_len, const char *name, | ||
5698 | size_t name_len, int type) | ||
5699 | { | ||
5700 | size_t len = 0; | ||
5701 | |||
5702 | if (nfs_server_capable(dentry->d_inode, NFS_CAP_SECURITY_LABEL)) { | ||
5703 | len = security_inode_listsecurity(dentry->d_inode, NULL, 0); | ||
5704 | if (list && len <= list_len) | ||
5705 | security_inode_listsecurity(dentry->d_inode, list, len); | ||
5706 | } | ||
5707 | return len; | ||
5708 | } | ||
5709 | |||
5710 | static const struct xattr_handler nfs4_xattr_nfs4_label_handler = { | ||
5711 | .prefix = XATTR_SECURITY_PREFIX, | ||
5712 | .list = nfs4_xattr_list_nfs4_label, | ||
5713 | .get = nfs4_xattr_get_nfs4_label, | ||
5714 | .set = nfs4_xattr_set_nfs4_label, | ||
5715 | }; | ||
5716 | #endif | ||
5717 | |||
5718 | |||
5327 | /* | 5719 | /* |
5328 | * nfs_fhget will use either the mounted_on_fileid or the fileid | 5720 | * nfs_fhget will use either the mounted_on_fileid or the fileid |
5329 | */ | 5721 | */ |
@@ -5347,7 +5739,7 @@ static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, | |||
5347 | struct page *page) | 5739 | struct page *page) |
5348 | { | 5740 | { |
5349 | struct nfs_server *server = NFS_SERVER(dir); | 5741 | struct nfs_server *server = NFS_SERVER(dir); |
5350 | u32 bitmask[2] = { | 5742 | u32 bitmask[3] = { |
5351 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, | 5743 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, |
5352 | }; | 5744 | }; |
5353 | struct nfs4_fs_locations_arg args = { | 5745 | struct nfs4_fs_locations_arg args = { |
@@ -7052,11 +7444,33 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | |||
7052 | }; | 7444 | }; |
7053 | #endif | 7445 | #endif |
7054 | 7446 | ||
7447 | #if defined(CONFIG_NFS_V4_2) | ||
7448 | static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { | ||
7449 | .minor_version = 2, | ||
7450 | .init_caps = NFS_CAP_READDIRPLUS | ||
7451 | | NFS_CAP_ATOMIC_OPEN | ||
7452 | | NFS_CAP_CHANGE_ATTR | ||
7453 | | NFS_CAP_POSIX_LOCK | ||
7454 | | NFS_CAP_STATEID_NFSV41 | ||
7455 | | NFS_CAP_ATOMIC_OPEN_V1, | ||
7456 | .call_sync = nfs4_call_sync_sequence, | ||
7457 | .match_stateid = nfs41_match_stateid, | ||
7458 | .find_root_sec = nfs41_find_root_sec, | ||
7459 | .free_lock_state = nfs41_free_lock_state, | ||
7460 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | ||
7461 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | ||
7462 | .state_renewal_ops = &nfs41_state_renewal_ops, | ||
7463 | }; | ||
7464 | #endif | ||
7465 | |||
7055 | const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { | 7466 | const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { |
7056 | [0] = &nfs_v4_0_minor_ops, | 7467 | [0] = &nfs_v4_0_minor_ops, |
7057 | #if defined(CONFIG_NFS_V4_1) | 7468 | #if defined(CONFIG_NFS_V4_1) |
7058 | [1] = &nfs_v4_1_minor_ops, | 7469 | [1] = &nfs_v4_1_minor_ops, |
7059 | #endif | 7470 | #endif |
7471 | #if defined(CONFIG_NFS_V4_2) | ||
7472 | [2] = &nfs_v4_2_minor_ops, | ||
7473 | #endif | ||
7060 | }; | 7474 | }; |
7061 | 7475 | ||
7062 | const struct inode_operations nfs4_dir_inode_operations = { | 7476 | const struct inode_operations nfs4_dir_inode_operations = { |
@@ -7156,6 +7570,9 @@ static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { | |||
7156 | 7570 | ||
7157 | const struct xattr_handler *nfs4_xattr_handlers[] = { | 7571 | const struct xattr_handler *nfs4_xattr_handlers[] = { |
7158 | &nfs4_xattr_nfs4_acl_handler, | 7572 | &nfs4_xattr_nfs4_acl_handler, |
7573 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
7574 | &nfs4_xattr_nfs4_label_handler, | ||
7575 | #endif | ||
7159 | NULL | 7576 | NULL |
7160 | }; | 7577 | }; |
7161 | 7578 | ||
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 27cc76d88f9a..0abfb8466e79 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -102,12 +102,23 @@ static int nfs4_stat_to_errno(int); | |||
102 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) | 102 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) |
103 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 103 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
104 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 104 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
105 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
106 | /* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */ | ||
107 | #define nfs4_label_maxsz (4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN)) | ||
108 | #define encode_readdir_space 24 | ||
109 | #define encode_readdir_bitmask_sz 3 | ||
110 | #else | ||
111 | #define nfs4_label_maxsz 0 | ||
112 | #define encode_readdir_space 20 | ||
113 | #define encode_readdir_bitmask_sz 2 | ||
114 | #endif | ||
105 | /* We support only one layout type per file system */ | 115 | /* We support only one layout type per file system */ |
106 | #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) | 116 | #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) |
107 | /* This is based on getfattr, which uses the most attributes: */ | 117 | /* This is based on getfattr, which uses the most attributes: */ |
108 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ | 118 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ |
109 | 3 + 3 + 3 + nfs4_owner_maxsz + \ | 119 | 3 + 3 + 3 + nfs4_owner_maxsz + \ |
110 | nfs4_group_maxsz + decode_mdsthreshold_maxsz)) | 120 | nfs4_group_maxsz + nfs4_label_maxsz + \ |
121 | decode_mdsthreshold_maxsz)) | ||
111 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ | 122 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ |
112 | nfs4_fattr_value_maxsz) | 123 | nfs4_fattr_value_maxsz) |
113 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) | 124 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) |
@@ -115,6 +126,7 @@ static int nfs4_stat_to_errno(int); | |||
115 | 1 + 2 + 1 + \ | 126 | 1 + 2 + 1 + \ |
116 | nfs4_owner_maxsz + \ | 127 | nfs4_owner_maxsz + \ |
117 | nfs4_group_maxsz + \ | 128 | nfs4_group_maxsz + \ |
129 | nfs4_label_maxsz + \ | ||
118 | 4 + 4) | 130 | 4 + 4) |
119 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) | 131 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) |
120 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) | 132 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) |
@@ -192,9 +204,11 @@ static int nfs4_stat_to_errno(int); | |||
192 | encode_stateid_maxsz + 3) | 204 | encode_stateid_maxsz + 3) |
193 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2) | 205 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2) |
194 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ | 206 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ |
195 | 2 + encode_verifier_maxsz + 5) | 207 | 2 + encode_verifier_maxsz + 5 + \ |
208 | nfs4_label_maxsz) | ||
196 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ | 209 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ |
197 | decode_verifier_maxsz) | 210 | decode_verifier_maxsz + \ |
211 | nfs4_label_maxsz + nfs4_fattr_maxsz) | ||
198 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) | 212 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) |
199 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) | 213 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) |
200 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ | 214 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ |
@@ -974,7 +988,9 @@ static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *ve | |||
974 | encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); | 988 | encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); |
975 | } | 989 | } |
976 | 990 | ||
977 | static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server) | 991 | static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, |
992 | const struct nfs4_label *label, | ||
993 | const struct nfs_server *server) | ||
978 | { | 994 | { |
979 | char owner_name[IDMAP_NAMESZ]; | 995 | char owner_name[IDMAP_NAMESZ]; |
980 | char owner_group[IDMAP_NAMESZ]; | 996 | char owner_group[IDMAP_NAMESZ]; |
@@ -985,15 +1001,16 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
985 | int len; | 1001 | int len; |
986 | uint32_t bmval0 = 0; | 1002 | uint32_t bmval0 = 0; |
987 | uint32_t bmval1 = 0; | 1003 | uint32_t bmval1 = 0; |
1004 | uint32_t bmval2 = 0; | ||
988 | 1005 | ||
989 | /* | 1006 | /* |
990 | * We reserve enough space to write the entire attribute buffer at once. | 1007 | * We reserve enough space to write the entire attribute buffer at once. |
991 | * In the worst-case, this would be | 1008 | * In the worst-case, this would be |
992 | * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) | 1009 | * 16(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) |
993 | * = 36 bytes, plus any contribution from variable-length fields | 1010 | * = 40 bytes, plus any contribution from variable-length fields |
994 | * such as owner/group. | 1011 | * such as owner/group. |
995 | */ | 1012 | */ |
996 | len = 16; | 1013 | len = 20; |
997 | 1014 | ||
998 | /* Sigh */ | 1015 | /* Sigh */ |
999 | if (iap->ia_valid & ATTR_SIZE) | 1016 | if (iap->ia_valid & ATTR_SIZE) |
@@ -1023,6 +1040,8 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
1023 | } | 1040 | } |
1024 | len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); | 1041 | len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); |
1025 | } | 1042 | } |
1043 | if (label) | ||
1044 | len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); | ||
1026 | if (iap->ia_valid & ATTR_ATIME_SET) | 1045 | if (iap->ia_valid & ATTR_ATIME_SET) |
1027 | len += 16; | 1046 | len += 16; |
1028 | else if (iap->ia_valid & ATTR_ATIME) | 1047 | else if (iap->ia_valid & ATTR_ATIME) |
@@ -1037,9 +1056,9 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
1037 | * We write the bitmap length now, but leave the bitmap and the attribute | 1056 | * We write the bitmap length now, but leave the bitmap and the attribute |
1038 | * buffer length to be backfilled at the end of this routine. | 1057 | * buffer length to be backfilled at the end of this routine. |
1039 | */ | 1058 | */ |
1040 | *p++ = cpu_to_be32(2); | 1059 | *p++ = cpu_to_be32(3); |
1041 | q = p; | 1060 | q = p; |
1042 | p += 3; | 1061 | p += 4; |
1043 | 1062 | ||
1044 | if (iap->ia_valid & ATTR_SIZE) { | 1063 | if (iap->ia_valid & ATTR_SIZE) { |
1045 | bmval0 |= FATTR4_WORD0_SIZE; | 1064 | bmval0 |= FATTR4_WORD0_SIZE; |
@@ -1077,6 +1096,13 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
1077 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; | 1096 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; |
1078 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); | 1097 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); |
1079 | } | 1098 | } |
1099 | if (label) { | ||
1100 | bmval2 |= FATTR4_WORD2_SECURITY_LABEL; | ||
1101 | *p++ = cpu_to_be32(label->lfs); | ||
1102 | *p++ = cpu_to_be32(label->pi); | ||
1103 | *p++ = cpu_to_be32(label->len); | ||
1104 | p = xdr_encode_opaque_fixed(p, label->label, label->len); | ||
1105 | } | ||
1080 | 1106 | ||
1081 | /* | 1107 | /* |
1082 | * Now we backfill the bitmap and the attribute buffer length. | 1108 | * Now we backfill the bitmap and the attribute buffer length. |
@@ -1086,9 +1112,10 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
1086 | len, ((char *)p - (char *)q) + 4); | 1112 | len, ((char *)p - (char *)q) + 4); |
1087 | BUG(); | 1113 | BUG(); |
1088 | } | 1114 | } |
1089 | len = (char *)p - (char *)q - 12; | 1115 | len = (char *)p - (char *)q - 16; |
1090 | *q++ = htonl(bmval0); | 1116 | *q++ = htonl(bmval0); |
1091 | *q++ = htonl(bmval1); | 1117 | *q++ = htonl(bmval1); |
1118 | *q++ = htonl(bmval2); | ||
1092 | *q = htonl(len); | 1119 | *q = htonl(len); |
1093 | 1120 | ||
1094 | /* out: */ | 1121 | /* out: */ |
@@ -1142,7 +1169,7 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg * | |||
1142 | } | 1169 | } |
1143 | 1170 | ||
1144 | encode_string(xdr, create->name->len, create->name->name); | 1171 | encode_string(xdr, create->name->len, create->name->name); |
1145 | encode_attrs(xdr, create->attrs, create->server); | 1172 | encode_attrs(xdr, create->attrs, create->label, create->server); |
1146 | } | 1173 | } |
1147 | 1174 | ||
1148 | static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) | 1175 | static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) |
@@ -1194,8 +1221,10 @@ encode_getattr_three(struct xdr_stream *xdr, | |||
1194 | 1221 | ||
1195 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1222 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
1196 | { | 1223 | { |
1197 | encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0], | 1224 | encode_getattr_three(xdr, bitmask[0] & nfs4_fattr_bitmap[0], |
1198 | bitmask[1] & nfs4_fattr_bitmap[1], hdr); | 1225 | bitmask[1] & nfs4_fattr_bitmap[1], |
1226 | bitmask[2] & nfs4_fattr_bitmap[2], | ||
1227 | hdr); | ||
1199 | } | 1228 | } |
1200 | 1229 | ||
1201 | static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, | 1230 | static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, |
@@ -1373,11 +1402,11 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op | |||
1373 | switch(arg->createmode) { | 1402 | switch(arg->createmode) { |
1374 | case NFS4_CREATE_UNCHECKED: | 1403 | case NFS4_CREATE_UNCHECKED: |
1375 | *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); | 1404 | *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); |
1376 | encode_attrs(xdr, arg->u.attrs, arg->server); | 1405 | encode_attrs(xdr, arg->u.attrs, arg->label, arg->server); |
1377 | break; | 1406 | break; |
1378 | case NFS4_CREATE_GUARDED: | 1407 | case NFS4_CREATE_GUARDED: |
1379 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); | 1408 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); |
1380 | encode_attrs(xdr, arg->u.attrs, arg->server); | 1409 | encode_attrs(xdr, arg->u.attrs, arg->label, arg->server); |
1381 | break; | 1410 | break; |
1382 | case NFS4_CREATE_EXCLUSIVE: | 1411 | case NFS4_CREATE_EXCLUSIVE: |
1383 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); | 1412 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); |
@@ -1387,7 +1416,7 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op | |||
1387 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); | 1416 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); |
1388 | encode_nfs4_verifier(xdr, &arg->u.verifier); | 1417 | encode_nfs4_verifier(xdr, &arg->u.verifier); |
1389 | dummy.ia_valid = 0; | 1418 | dummy.ia_valid = 0; |
1390 | encode_attrs(xdr, &dummy, arg->server); | 1419 | encode_attrs(xdr, &dummy, arg->label, arg->server); |
1391 | } | 1420 | } |
1392 | } | 1421 | } |
1393 | 1422 | ||
@@ -1538,7 +1567,7 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, | |||
1538 | 1567 | ||
1539 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) | 1568 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) |
1540 | { | 1569 | { |
1541 | uint32_t attrs[2] = { | 1570 | uint32_t attrs[3] = { |
1542 | FATTR4_WORD0_RDATTR_ERROR, | 1571 | FATTR4_WORD0_RDATTR_ERROR, |
1543 | FATTR4_WORD1_MOUNTED_ON_FILEID, | 1572 | FATTR4_WORD1_MOUNTED_ON_FILEID, |
1544 | }; | 1573 | }; |
@@ -1561,20 +1590,26 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg | |||
1561 | encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); | 1590 | encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); |
1562 | encode_uint64(xdr, readdir->cookie); | 1591 | encode_uint64(xdr, readdir->cookie); |
1563 | encode_nfs4_verifier(xdr, &readdir->verifier); | 1592 | encode_nfs4_verifier(xdr, &readdir->verifier); |
1564 | p = reserve_space(xdr, 20); | 1593 | p = reserve_space(xdr, encode_readdir_space); |
1565 | *p++ = cpu_to_be32(dircount); | 1594 | *p++ = cpu_to_be32(dircount); |
1566 | *p++ = cpu_to_be32(readdir->count); | 1595 | *p++ = cpu_to_be32(readdir->count); |
1567 | *p++ = cpu_to_be32(2); | 1596 | *p++ = cpu_to_be32(encode_readdir_bitmask_sz); |
1568 | |||
1569 | *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); | 1597 | *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); |
1570 | *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); | 1598 | *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); |
1599 | if (encode_readdir_bitmask_sz > 2) { | ||
1600 | if (hdr->minorversion > 1) | ||
1601 | attrs[2] |= FATTR4_WORD2_SECURITY_LABEL; | ||
1602 | p++, *p++ = cpu_to_be32(attrs[2] & readdir->bitmask[2]); | ||
1603 | } | ||
1571 | memcpy(verf, readdir->verifier.data, sizeof(verf)); | 1604 | memcpy(verf, readdir->verifier.data, sizeof(verf)); |
1572 | dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", | 1605 | |
1606 | dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n", | ||
1573 | __func__, | 1607 | __func__, |
1574 | (unsigned long long)readdir->cookie, | 1608 | (unsigned long long)readdir->cookie, |
1575 | verf[0], verf[1], | 1609 | verf[0], verf[1], |
1576 | attrs[0] & readdir->bitmask[0], | 1610 | attrs[0] & readdir->bitmask[0], |
1577 | attrs[1] & readdir->bitmask[1]); | 1611 | attrs[1] & readdir->bitmask[1], |
1612 | attrs[2] & readdir->bitmask[2]); | ||
1578 | } | 1613 | } |
1579 | 1614 | ||
1580 | static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) | 1615 | static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) |
@@ -1633,7 +1668,7 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs | |||
1633 | { | 1668 | { |
1634 | encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); | 1669 | encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); |
1635 | encode_nfs4_stateid(xdr, &arg->stateid); | 1670 | encode_nfs4_stateid(xdr, &arg->stateid); |
1636 | encode_attrs(xdr, arg->iap, server); | 1671 | encode_attrs(xdr, arg->iap, arg->label, server); |
1637 | } | 1672 | } |
1638 | 1673 | ||
1639 | static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) | 1674 | static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) |
@@ -4044,6 +4079,56 @@ static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4044 | return status; | 4079 | return status; |
4045 | } | 4080 | } |
4046 | 4081 | ||
4082 | static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, | ||
4083 | struct nfs4_label *label) | ||
4084 | { | ||
4085 | uint32_t pi = 0; | ||
4086 | uint32_t lfs = 0; | ||
4087 | __u32 len; | ||
4088 | __be32 *p; | ||
4089 | int status = 0; | ||
4090 | |||
4091 | if (unlikely(bitmap[2] & (FATTR4_WORD2_SECURITY_LABEL - 1U))) | ||
4092 | return -EIO; | ||
4093 | if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) { | ||
4094 | p = xdr_inline_decode(xdr, 4); | ||
4095 | if (unlikely(!p)) | ||
4096 | goto out_overflow; | ||
4097 | lfs = be32_to_cpup(p++); | ||
4098 | p = xdr_inline_decode(xdr, 4); | ||
4099 | if (unlikely(!p)) | ||
4100 | goto out_overflow; | ||
4101 | pi = be32_to_cpup(p++); | ||
4102 | p = xdr_inline_decode(xdr, 4); | ||
4103 | if (unlikely(!p)) | ||
4104 | goto out_overflow; | ||
4105 | len = be32_to_cpup(p++); | ||
4106 | p = xdr_inline_decode(xdr, len); | ||
4107 | if (unlikely(!p)) | ||
4108 | goto out_overflow; | ||
4109 | if (len < NFS4_MAXLABELLEN) { | ||
4110 | if (label) { | ||
4111 | memcpy(label->label, p, len); | ||
4112 | label->len = len; | ||
4113 | label->pi = pi; | ||
4114 | label->lfs = lfs; | ||
4115 | status = NFS_ATTR_FATTR_V4_SECURITY_LABEL; | ||
4116 | } | ||
4117 | bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL; | ||
4118 | } else | ||
4119 | printk(KERN_WARNING "%s: label too long (%u)!\n", | ||
4120 | __func__, len); | ||
4121 | } | ||
4122 | if (label && label->label) | ||
4123 | dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__, | ||
4124 | (char *)label->label, label->len, label->pi, label->lfs); | ||
4125 | return status; | ||
4126 | |||
4127 | out_overflow: | ||
4128 | print_overflow_msg(__func__, xdr); | ||
4129 | return -EIO; | ||
4130 | } | ||
4131 | |||
4047 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) | 4132 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) |
4048 | { | 4133 | { |
4049 | int status = 0; | 4134 | int status = 0; |
@@ -4386,7 +4471,7 @@ out_overflow: | |||
4386 | 4471 | ||
4387 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | 4472 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, |
4388 | struct nfs_fattr *fattr, struct nfs_fh *fh, | 4473 | struct nfs_fattr *fattr, struct nfs_fh *fh, |
4389 | struct nfs4_fs_locations *fs_loc, | 4474 | struct nfs4_fs_locations *fs_loc, struct nfs4_label *label, |
4390 | const struct nfs_server *server) | 4475 | const struct nfs_server *server) |
4391 | { | 4476 | { |
4392 | int status; | 4477 | int status; |
@@ -4494,6 +4579,13 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4494 | if (status < 0) | 4579 | if (status < 0) |
4495 | goto xdr_error; | 4580 | goto xdr_error; |
4496 | 4581 | ||
4582 | if (label) { | ||
4583 | status = decode_attr_security_label(xdr, bitmap, label); | ||
4584 | if (status < 0) | ||
4585 | goto xdr_error; | ||
4586 | fattr->valid |= status; | ||
4587 | } | ||
4588 | |||
4497 | xdr_error: | 4589 | xdr_error: |
4498 | dprintk("%s: xdr returned %d\n", __func__, -status); | 4590 | dprintk("%s: xdr returned %d\n", __func__, -status); |
4499 | return status; | 4591 | return status; |
@@ -4501,7 +4593,7 @@ xdr_error: | |||
4501 | 4593 | ||
4502 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4594 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
4503 | struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, | 4595 | struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, |
4504 | const struct nfs_server *server) | 4596 | struct nfs4_label *label, const struct nfs_server *server) |
4505 | { | 4597 | { |
4506 | unsigned int savep; | 4598 | unsigned int savep; |
4507 | uint32_t attrlen, | 4599 | uint32_t attrlen, |
@@ -4520,7 +4612,8 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat | |||
4520 | if (status < 0) | 4612 | if (status < 0) |
4521 | goto xdr_error; | 4613 | goto xdr_error; |
4522 | 4614 | ||
4523 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, server); | 4615 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, |
4616 | label, server); | ||
4524 | if (status < 0) | 4617 | if (status < 0) |
4525 | goto xdr_error; | 4618 | goto xdr_error; |
4526 | 4619 | ||
@@ -4530,10 +4623,16 @@ xdr_error: | |||
4530 | return status; | 4623 | return status; |
4531 | } | 4624 | } |
4532 | 4625 | ||
4626 | static int decode_getfattr_label(struct xdr_stream *xdr, struct nfs_fattr *fattr, | ||
4627 | struct nfs4_label *label, const struct nfs_server *server) | ||
4628 | { | ||
4629 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, label, server); | ||
4630 | } | ||
4631 | |||
4533 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4632 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
4534 | const struct nfs_server *server) | 4633 | const struct nfs_server *server) |
4535 | { | 4634 | { |
4536 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, server); | 4635 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, NULL, server); |
4537 | } | 4636 | } |
4538 | 4637 | ||
4539 | /* | 4638 | /* |
@@ -5925,7 +6024,7 @@ static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
5925 | status = decode_getfh(xdr, res->fh); | 6024 | status = decode_getfh(xdr, res->fh); |
5926 | if (status) | 6025 | if (status) |
5927 | goto out; | 6026 | goto out; |
5928 | status = decode_getfattr(xdr, res->fattr, res->server); | 6027 | status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
5929 | out: | 6028 | out: |
5930 | return status; | 6029 | return status; |
5931 | } | 6030 | } |
@@ -5951,7 +6050,8 @@ static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, | |||
5951 | goto out; | 6050 | goto out; |
5952 | status = decode_getfh(xdr, res->fh); | 6051 | status = decode_getfh(xdr, res->fh); |
5953 | if (status == 0) | 6052 | if (status == 0) |
5954 | status = decode_getfattr(xdr, res->fattr, res->server); | 6053 | status = decode_getfattr_label(xdr, res->fattr, |
6054 | res->label, res->server); | ||
5955 | out: | 6055 | out: |
5956 | return status; | 6056 | return status; |
5957 | } | 6057 | } |
@@ -6042,7 +6142,7 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6042 | status = decode_restorefh(xdr); | 6142 | status = decode_restorefh(xdr); |
6043 | if (status) | 6143 | if (status) |
6044 | goto out; | 6144 | goto out; |
6045 | decode_getfattr(xdr, res->fattr, res->server); | 6145 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6046 | out: | 6146 | out: |
6047 | return status; | 6147 | return status; |
6048 | } | 6148 | } |
@@ -6071,7 +6171,7 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6071 | status = decode_getfh(xdr, res->fh); | 6171 | status = decode_getfh(xdr, res->fh); |
6072 | if (status) | 6172 | if (status) |
6073 | goto out; | 6173 | goto out; |
6074 | decode_getfattr(xdr, res->fattr, res->server); | 6174 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6075 | out: | 6175 | out: |
6076 | return status; | 6176 | return status; |
6077 | } | 6177 | } |
@@ -6103,7 +6203,7 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6103 | status = decode_putfh(xdr); | 6203 | status = decode_putfh(xdr); |
6104 | if (status) | 6204 | if (status) |
6105 | goto out; | 6205 | goto out; |
6106 | status = decode_getfattr(xdr, res->fattr, res->server); | 6206 | status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6107 | out: | 6207 | out: |
6108 | return status; | 6208 | return status; |
6109 | } | 6209 | } |
@@ -6236,7 +6336,7 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6236 | goto out; | 6336 | goto out; |
6237 | if (res->access_request) | 6337 | if (res->access_request) |
6238 | decode_access(xdr, &res->access_supported, &res->access_result); | 6338 | decode_access(xdr, &res->access_supported, &res->access_result); |
6239 | decode_getfattr(xdr, res->f_attr, res->server); | 6339 | decode_getfattr_label(xdr, res->f_attr, res->f_label, res->server); |
6240 | out: | 6340 | out: |
6241 | return status; | 6341 | return status; |
6242 | } | 6342 | } |
@@ -6313,7 +6413,7 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, | |||
6313 | status = decode_setattr(xdr); | 6413 | status = decode_setattr(xdr); |
6314 | if (status) | 6414 | if (status) |
6315 | goto out; | 6415 | goto out; |
6316 | decode_getfattr(xdr, res->fattr, res->server); | 6416 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6317 | out: | 6417 | out: |
6318 | return status; | 6418 | return status; |
6319 | } | 6419 | } |
@@ -6702,7 +6802,7 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, | |||
6702 | xdr_enter_page(xdr, PAGE_SIZE); | 6802 | xdr_enter_page(xdr, PAGE_SIZE); |
6703 | status = decode_getfattr_generic(xdr, &res->fs_locations->fattr, | 6803 | status = decode_getfattr_generic(xdr, &res->fs_locations->fattr, |
6704 | NULL, res->fs_locations, | 6804 | NULL, res->fs_locations, |
6705 | res->fs_locations->server); | 6805 | NULL, res->fs_locations->server); |
6706 | out: | 6806 | out: |
6707 | return status; | 6807 | return status; |
6708 | } | 6808 | } |
@@ -7115,7 +7215,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
7115 | goto out_overflow; | 7215 | goto out_overflow; |
7116 | 7216 | ||
7117 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, | 7217 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, |
7118 | NULL, entry->server) < 0) | 7218 | NULL, entry->label, entry->server) < 0) |
7119 | goto out_overflow; | 7219 | goto out_overflow; |
7120 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) | 7220 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) |
7121 | entry->ino = entry->fattr->mounted_on_fileid; | 7221 | entry->ino = entry->fattr->mounted_on_fileid; |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index fc8de9016acf..c041c41f7a52 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -98,7 +98,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
98 | */ | 98 | */ |
99 | static int | 99 | static int |
100 | nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | 100 | nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, |
101 | struct nfs_fattr *fattr) | 101 | struct nfs_fattr *fattr, struct nfs4_label *label) |
102 | { | 102 | { |
103 | struct rpc_message msg = { | 103 | struct rpc_message msg = { |
104 | .rpc_proc = &nfs_procedures[NFSPROC_GETATTR], | 104 | .rpc_proc = &nfs_procedures[NFSPROC_GETATTR], |
@@ -146,7 +146,8 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
146 | 146 | ||
147 | static int | 147 | static int |
148 | nfs_proc_lookup(struct inode *dir, struct qstr *name, | 148 | nfs_proc_lookup(struct inode *dir, struct qstr *name, |
149 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 149 | struct nfs_fh *fhandle, struct nfs_fattr *fattr, |
150 | struct nfs4_label *label) | ||
150 | { | 151 | { |
151 | struct nfs_diropargs arg = { | 152 | struct nfs_diropargs arg = { |
152 | .fh = NFS_FH(dir), | 153 | .fh = NFS_FH(dir), |
@@ -243,7 +244,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
243 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 244 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
244 | nfs_mark_for_revalidate(dir); | 245 | nfs_mark_for_revalidate(dir); |
245 | if (status == 0) | 246 | if (status == 0) |
246 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 247 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); |
247 | nfs_free_createdata(data); | 248 | nfs_free_createdata(data); |
248 | out: | 249 | out: |
249 | dprintk("NFS reply create: %d\n", status); | 250 | dprintk("NFS reply create: %d\n", status); |
@@ -290,7 +291,7 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
290 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 291 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
291 | } | 292 | } |
292 | if (status == 0) | 293 | if (status == 0) |
293 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 294 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); |
294 | nfs_free_createdata(data); | 295 | nfs_free_createdata(data); |
295 | out: | 296 | out: |
296 | dprintk("NFS reply mknod: %d\n", status); | 297 | dprintk("NFS reply mknod: %d\n", status); |
@@ -442,7 +443,7 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | |||
442 | * should fill in the data with a LOOKUP call on the wire. | 443 | * should fill in the data with a LOOKUP call on the wire. |
443 | */ | 444 | */ |
444 | if (status == 0) | 445 | if (status == 0) |
445 | status = nfs_instantiate(dentry, fh, fattr); | 446 | status = nfs_instantiate(dentry, fh, fattr, NULL); |
446 | 447 | ||
447 | out_free: | 448 | out_free: |
448 | nfs_free_fattr(fattr); | 449 | nfs_free_fattr(fattr); |
@@ -471,7 +472,7 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) | |||
471 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 472 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
472 | nfs_mark_for_revalidate(dir); | 473 | nfs_mark_for_revalidate(dir); |
473 | if (status == 0) | 474 | if (status == 0) |
474 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 475 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); |
475 | nfs_free_createdata(data); | 476 | nfs_free_createdata(data); |
476 | out: | 477 | out: |
477 | dprintk("NFS reply mkdir: %d\n", status); | 478 | dprintk("NFS reply mkdir: %d\n", status); |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 8d51101771fc..71fdc0dfa0d2 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -269,7 +269,7 @@ static match_table_t nfs_local_lock_tokens = { | |||
269 | 269 | ||
270 | enum { | 270 | enum { |
271 | Opt_vers_2, Opt_vers_3, Opt_vers_4, Opt_vers_4_0, | 271 | Opt_vers_2, Opt_vers_3, Opt_vers_4, Opt_vers_4_0, |
272 | Opt_vers_4_1, | 272 | Opt_vers_4_1, Opt_vers_4_2, |
273 | 273 | ||
274 | Opt_vers_err | 274 | Opt_vers_err |
275 | }; | 275 | }; |
@@ -280,6 +280,7 @@ static match_table_t nfs_vers_tokens = { | |||
280 | { Opt_vers_4, "4" }, | 280 | { Opt_vers_4, "4" }, |
281 | { Opt_vers_4_0, "4.0" }, | 281 | { Opt_vers_4_0, "4.0" }, |
282 | { Opt_vers_4_1, "4.1" }, | 282 | { Opt_vers_4_1, "4.1" }, |
283 | { Opt_vers_4_2, "4.2" }, | ||
283 | 284 | ||
284 | { Opt_vers_err, NULL } | 285 | { Opt_vers_err, NULL } |
285 | }; | 286 | }; |
@@ -832,6 +833,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root) | |||
832 | seq_printf(m, "\n\tnfsv4:\t"); | 833 | seq_printf(m, "\n\tnfsv4:\t"); |
833 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); | 834 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); |
834 | seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); | 835 | seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); |
836 | seq_printf(m, ",bm2=0x%x", nfss->attr_bitmask[2]); | ||
835 | seq_printf(m, ",acl=0x%x", nfss->acl_bitmask); | 837 | seq_printf(m, ",acl=0x%x", nfss->acl_bitmask); |
836 | show_sessions(m, nfss); | 838 | show_sessions(m, nfss); |
837 | show_pnfs(m, nfss); | 839 | show_pnfs(m, nfss); |
@@ -1097,6 +1099,10 @@ static int nfs_parse_version_string(char *string, | |||
1097 | mnt->version = 4; | 1099 | mnt->version = 4; |
1098 | mnt->minorversion = 1; | 1100 | mnt->minorversion = 1; |
1099 | break; | 1101 | break; |
1102 | case Opt_vers_4_2: | ||
1103 | mnt->version = 4; | ||
1104 | mnt->minorversion = 2; | ||
1105 | break; | ||
1100 | default: | 1106 | default: |
1101 | return 0; | 1107 | return 0; |
1102 | } | 1108 | } |
@@ -2423,7 +2429,21 @@ static int nfs_bdi_register(struct nfs_server *server) | |||
2423 | int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, | 2429 | int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, |
2424 | struct nfs_mount_info *mount_info) | 2430 | struct nfs_mount_info *mount_info) |
2425 | { | 2431 | { |
2426 | return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts); | 2432 | int error; |
2433 | unsigned long kflags = 0, kflags_out = 0; | ||
2434 | if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL) | ||
2435 | kflags |= SECURITY_LSM_NATIVE_LABELS; | ||
2436 | |||
2437 | error = security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts, | ||
2438 | kflags, &kflags_out); | ||
2439 | if (error) | ||
2440 | goto err; | ||
2441 | |||
2442 | if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL && | ||
2443 | !(kflags_out & SECURITY_LSM_NATIVE_LABELS)) | ||
2444 | NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL; | ||
2445 | err: | ||
2446 | return error; | ||
2427 | } | 2447 | } |
2428 | EXPORT_SYMBOL_GPL(nfs_set_sb_security); | 2448 | EXPORT_SYMBOL_GPL(nfs_set_sb_security); |
2429 | 2449 | ||
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 07a473fd49bc..c0d93170585d 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h | |||
@@ -243,6 +243,12 @@ void nfsd_lockd_shutdown(void); | |||
243 | #define nfserr_reject_deleg cpu_to_be32(NFS4ERR_REJECT_DELEG) | 243 | #define nfserr_reject_deleg cpu_to_be32(NFS4ERR_REJECT_DELEG) |
244 | #define nfserr_returnconflict cpu_to_be32(NFS4ERR_RETURNCONFLICT) | 244 | #define nfserr_returnconflict cpu_to_be32(NFS4ERR_RETURNCONFLICT) |
245 | #define nfserr_deleg_revoked cpu_to_be32(NFS4ERR_DELEG_REVOKED) | 245 | #define nfserr_deleg_revoked cpu_to_be32(NFS4ERR_DELEG_REVOKED) |
246 | #define nfserr_partner_notsupp cpu_to_be32(NFS4ERR_PARTNER_NOTSUPP) | ||
247 | #define nfserr_partner_no_auth cpu_to_be32(NFS4ERR_PARTNER_NO_AUTH) | ||
248 | #define nfserr_metadata_notsupp cpu_to_be32(NFS4ERR_METADATA_NOTSUPP) | ||
249 | #define nfserr_offload_denied cpu_to_be32(NFS4ERR_OFFLOAD_DENIED) | ||
250 | #define nfserr_wrong_lfs cpu_to_be32(NFS4ERR_WRONG_LFS) | ||
251 | #define nfserr_badlabel cpu_to_be32(NFS4ERR_BADLABEL) | ||
246 | 252 | ||
247 | /* error codes for internal use */ | 253 | /* error codes for internal use */ |
248 | /* if a request fails due to kmalloc failure, it gets dropped. | 254 | /* if a request fails due to kmalloc failure, it gets dropped. |
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 7b8fc73810ad..e36dee52f224 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
@@ -32,6 +32,15 @@ struct nfs4_acl { | |||
32 | struct nfs4_ace aces[0]; | 32 | struct nfs4_ace aces[0]; |
33 | }; | 33 | }; |
34 | 34 | ||
35 | #define NFS4_MAXLABELLEN 2048 | ||
36 | |||
37 | struct nfs4_label { | ||
38 | uint32_t lfs; | ||
39 | uint32_t pi; | ||
40 | u32 len; | ||
41 | char *label; | ||
42 | }; | ||
43 | |||
35 | typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier; | 44 | typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier; |
36 | 45 | ||
37 | struct nfs_stateid4 { | 46 | struct nfs_stateid4 { |
@@ -219,6 +228,14 @@ enum nfsstat4 { | |||
219 | NFS4ERR_REJECT_DELEG = 10085, /* on callback */ | 228 | NFS4ERR_REJECT_DELEG = 10085, /* on callback */ |
220 | NFS4ERR_RETURNCONFLICT = 10086, /* outstanding layoutreturn */ | 229 | NFS4ERR_RETURNCONFLICT = 10086, /* outstanding layoutreturn */ |
221 | NFS4ERR_DELEG_REVOKED = 10087, /* deleg./layout revoked */ | 230 | NFS4ERR_DELEG_REVOKED = 10087, /* deleg./layout revoked */ |
231 | |||
232 | /* nfs42 */ | ||
233 | NFS4ERR_PARTNER_NOTSUPP = 10088, | ||
234 | NFS4ERR_PARTNER_NO_AUTH = 10089, | ||
235 | NFS4ERR_METADATA_NOTSUPP = 10090, | ||
236 | NFS4ERR_OFFLOAD_DENIED = 10091, | ||
237 | NFS4ERR_WRONG_LFS = 10092, | ||
238 | NFS4ERR_BADLABEL = 10093, | ||
222 | }; | 239 | }; |
223 | 240 | ||
224 | static inline bool seqid_mutating_err(u32 err) | 241 | static inline bool seqid_mutating_err(u32 err) |
@@ -378,6 +395,7 @@ enum lock_type4 { | |||
378 | #define FATTR4_WORD1_FS_LAYOUT_TYPES (1UL << 30) | 395 | #define FATTR4_WORD1_FS_LAYOUT_TYPES (1UL << 30) |
379 | #define FATTR4_WORD2_LAYOUT_BLKSIZE (1UL << 1) | 396 | #define FATTR4_WORD2_LAYOUT_BLKSIZE (1UL << 1) |
380 | #define FATTR4_WORD2_MDSTHRESHOLD (1UL << 4) | 397 | #define FATTR4_WORD2_MDSTHRESHOLD (1UL << 4) |
398 | #define FATTR4_WORD2_SECURITY_LABEL (1UL << 17) | ||
381 | 399 | ||
382 | /* MDS threshold bitmap bits */ | 400 | /* MDS threshold bitmap bits */ |
383 | #define THRESHOLD_RD (1UL << 0) | 401 | #define THRESHOLD_RD (1UL << 0) |
@@ -390,11 +408,15 @@ enum lock_type4 { | |||
390 | #define NFS4_VERSION 4 | 408 | #define NFS4_VERSION 4 |
391 | #define NFS4_MINOR_VERSION 0 | 409 | #define NFS4_MINOR_VERSION 0 |
392 | 410 | ||
411 | #if defined(CONFIG_NFS_V4_2) | ||
412 | #define NFS4_MAX_MINOR_VERSION 2 | ||
413 | #else | ||
393 | #if defined(CONFIG_NFS_V4_1) | 414 | #if defined(CONFIG_NFS_V4_1) |
394 | #define NFS4_MAX_MINOR_VERSION 1 | 415 | #define NFS4_MAX_MINOR_VERSION 1 |
395 | #else | 416 | #else |
396 | #define NFS4_MAX_MINOR_VERSION 0 | 417 | #define NFS4_MAX_MINOR_VERSION 0 |
397 | #endif /* CONFIG_NFS_V4_1 */ | 418 | #endif /* CONFIG_NFS_V4_1 */ |
419 | #endif /* CONFIG_NFS_V4_2 */ | ||
398 | 420 | ||
399 | #define NFS4_DEBUG 1 | 421 | #define NFS4_DEBUG 1 |
400 | 422 | ||
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 1384ed92cad6..0b176297aaf6 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -207,6 +207,7 @@ struct nfs_inode { | |||
207 | #define NFS_INO_INVALID_ACL 0x0010 /* cached acls are invalid */ | 207 | #define NFS_INO_INVALID_ACL 0x0010 /* cached acls are invalid */ |
208 | #define NFS_INO_REVAL_PAGECACHE 0x0020 /* must revalidate pagecache */ | 208 | #define NFS_INO_REVAL_PAGECACHE 0x0020 /* must revalidate pagecache */ |
209 | #define NFS_INO_REVAL_FORCED 0x0040 /* force revalidation ignoring a delegation */ | 209 | #define NFS_INO_REVAL_FORCED 0x0040 /* force revalidation ignoring a delegation */ |
210 | #define NFS_INO_INVALID_LABEL 0x0080 /* cached label is invalid */ | ||
210 | 211 | ||
211 | /* | 212 | /* |
212 | * Bit offsets in flags field | 213 | * Bit offsets in flags field |
@@ -336,7 +337,7 @@ extern void nfs_zap_mapping(struct inode *inode, struct address_space *mapping); | |||
336 | extern void nfs_zap_caches(struct inode *); | 337 | extern void nfs_zap_caches(struct inode *); |
337 | extern void nfs_invalidate_atime(struct inode *); | 338 | extern void nfs_invalidate_atime(struct inode *); |
338 | extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, | 339 | extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, |
339 | struct nfs_fattr *); | 340 | struct nfs_fattr *, struct nfs4_label *); |
340 | extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); | 341 | extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); |
341 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); | 342 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); |
342 | extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); | 343 | extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); |
@@ -352,6 +353,8 @@ extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); | |||
352 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); | 353 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); |
353 | extern int nfs_setattr(struct dentry *, struct iattr *); | 354 | extern int nfs_setattr(struct dentry *, struct iattr *); |
354 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); | 355 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); |
356 | extern void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | ||
357 | struct nfs4_label *label); | ||
355 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); | 358 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); |
356 | extern void put_nfs_open_context(struct nfs_open_context *ctx); | 359 | extern void put_nfs_open_context(struct nfs_open_context *ctx); |
357 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode); | 360 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode); |
@@ -469,7 +472,8 @@ extern const struct file_operations nfs_dir_operations; | |||
469 | extern const struct dentry_operations nfs_dentry_operations; | 472 | extern const struct dentry_operations nfs_dentry_operations; |
470 | 473 | ||
471 | extern void nfs_force_lookup_revalidate(struct inode *dir); | 474 | extern void nfs_force_lookup_revalidate(struct inode *dir); |
472 | extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr); | 475 | extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, |
476 | struct nfs_fattr *fattr, struct nfs4_label *label); | ||
473 | extern int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags); | 477 | extern int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags); |
474 | extern void nfs_access_zap_cache(struct inode *inode); | 478 | extern void nfs_access_zap_cache(struct inode *inode); |
475 | 479 | ||
@@ -498,6 +502,24 @@ extern int nfs_mountpoint_expiry_timeout; | |||
498 | extern void nfs_release_automount_timer(void); | 502 | extern void nfs_release_automount_timer(void); |
499 | 503 | ||
500 | /* | 504 | /* |
505 | * linux/fs/nfs/nfs4proc.c | ||
506 | */ | ||
507 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
508 | extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags); | ||
509 | static inline void nfs4_label_free(struct nfs4_label *label) | ||
510 | { | ||
511 | if (label) { | ||
512 | kfree(label->label); | ||
513 | kfree(label); | ||
514 | } | ||
515 | return; | ||
516 | } | ||
517 | #else | ||
518 | static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; } | ||
519 | static inline void nfs4_label_free(void *label) {} | ||
520 | #endif | ||
521 | |||
522 | /* | ||
501 | * linux/fs/nfs/unlink.c | 523 | * linux/fs/nfs/unlink.c |
502 | */ | 524 | */ |
503 | extern void nfs_complete_unlink(struct dentry *dentry, struct inode *); | 525 | extern void nfs_complete_unlink(struct dentry *dentry, struct inode *); |
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 3b7fa2abecca..d2212432c456 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
@@ -146,7 +146,12 @@ struct nfs_server { | |||
146 | u32 attr_bitmask[3];/* V4 bitmask representing the set | 146 | u32 attr_bitmask[3];/* V4 bitmask representing the set |
147 | of attributes supported on this | 147 | of attributes supported on this |
148 | filesystem */ | 148 | filesystem */ |
149 | u32 cache_consistency_bitmask[2]; | 149 | u32 attr_bitmask_nl[3]; |
150 | /* V4 bitmask representing the | ||
151 | set of attributes supported | ||
152 | on this filesystem excluding | ||
153 | the label support bit. */ | ||
154 | u32 cache_consistency_bitmask[3]; | ||
150 | /* V4 bitmask representing the subset | 155 | /* V4 bitmask representing the subset |
151 | of change attribute, size, ctime | 156 | of change attribute, size, ctime |
152 | and mtime attributes supported by | 157 | and mtime attributes supported by |
@@ -200,5 +205,6 @@ struct nfs_server { | |||
200 | #define NFS_CAP_UIDGID_NOMAP (1U << 15) | 205 | #define NFS_CAP_UIDGID_NOMAP (1U << 15) |
201 | #define NFS_CAP_STATEID_NFSV41 (1U << 16) | 206 | #define NFS_CAP_STATEID_NFSV41 (1U << 16) |
202 | #define NFS_CAP_ATOMIC_OPEN_V1 (1U << 17) | 207 | #define NFS_CAP_ATOMIC_OPEN_V1 (1U << 17) |
208 | #define NFS_CAP_SECURITY_LABEL (1U << 18) | ||
203 | 209 | ||
204 | #endif | 210 | #endif |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 32c95d64e3aa..8651574a305b 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -101,6 +101,7 @@ struct nfs_fattr { | |||
101 | #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 22) | 101 | #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 22) |
102 | #define NFS_ATTR_FATTR_OWNER_NAME (1U << 23) | 102 | #define NFS_ATTR_FATTR_OWNER_NAME (1U << 23) |
103 | #define NFS_ATTR_FATTR_GROUP_NAME (1U << 24) | 103 | #define NFS_ATTR_FATTR_GROUP_NAME (1U << 24) |
104 | #define NFS_ATTR_FATTR_V4_SECURITY_LABEL (1U << 25) | ||
104 | 105 | ||
105 | #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ | 106 | #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ |
106 | | NFS_ATTR_FATTR_MODE \ | 107 | | NFS_ATTR_FATTR_MODE \ |
@@ -120,7 +121,8 @@ struct nfs_fattr { | |||
120 | #define NFS_ATTR_FATTR_V3 (NFS_ATTR_FATTR \ | 121 | #define NFS_ATTR_FATTR_V3 (NFS_ATTR_FATTR \ |
121 | | NFS_ATTR_FATTR_SPACE_USED) | 122 | | NFS_ATTR_FATTR_SPACE_USED) |
122 | #define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \ | 123 | #define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \ |
123 | | NFS_ATTR_FATTR_SPACE_USED) | 124 | | NFS_ATTR_FATTR_SPACE_USED \ |
125 | | NFS_ATTR_FATTR_V4_SECURITY_LABEL) | ||
124 | 126 | ||
125 | /* | 127 | /* |
126 | * Info on the file system | 128 | * Info on the file system |
@@ -348,6 +350,7 @@ struct nfs_openargs { | |||
348 | const u32 * open_bitmap; | 350 | const u32 * open_bitmap; |
349 | __u32 claim; | 351 | __u32 claim; |
350 | enum createmode4 createmode; | 352 | enum createmode4 createmode; |
353 | const struct nfs4_label *label; | ||
351 | }; | 354 | }; |
352 | 355 | ||
353 | struct nfs_openres { | 356 | struct nfs_openres { |
@@ -357,6 +360,7 @@ struct nfs_openres { | |||
357 | struct nfs4_change_info cinfo; | 360 | struct nfs4_change_info cinfo; |
358 | __u32 rflags; | 361 | __u32 rflags; |
359 | struct nfs_fattr * f_attr; | 362 | struct nfs_fattr * f_attr; |
363 | struct nfs4_label *f_label; | ||
360 | struct nfs_seqid * seqid; | 364 | struct nfs_seqid * seqid; |
361 | const struct nfs_server *server; | 365 | const struct nfs_server *server; |
362 | fmode_t delegation_type; | 366 | fmode_t delegation_type; |
@@ -599,6 +603,7 @@ struct nfs_entry { | |||
599 | int eof; | 603 | int eof; |
600 | struct nfs_fh * fh; | 604 | struct nfs_fh * fh; |
601 | struct nfs_fattr * fattr; | 605 | struct nfs_fattr * fattr; |
606 | struct nfs4_label *label; | ||
602 | unsigned char d_type; | 607 | unsigned char d_type; |
603 | struct nfs_server * server; | 608 | struct nfs_server * server; |
604 | }; | 609 | }; |
@@ -631,6 +636,7 @@ struct nfs_setattrargs { | |||
631 | struct iattr * iap; | 636 | struct iattr * iap; |
632 | const struct nfs_server * server; /* Needed for name mapping */ | 637 | const struct nfs_server * server; /* Needed for name mapping */ |
633 | const u32 * bitmask; | 638 | const u32 * bitmask; |
639 | const struct nfs4_label *label; | ||
634 | }; | 640 | }; |
635 | 641 | ||
636 | struct nfs_setaclargs { | 642 | struct nfs_setaclargs { |
@@ -666,6 +672,7 @@ struct nfs_getaclres { | |||
666 | struct nfs_setattrres { | 672 | struct nfs_setattrres { |
667 | struct nfs4_sequence_res seq_res; | 673 | struct nfs4_sequence_res seq_res; |
668 | struct nfs_fattr * fattr; | 674 | struct nfs_fattr * fattr; |
675 | struct nfs4_label *label; | ||
669 | const struct nfs_server * server; | 676 | const struct nfs_server * server; |
670 | }; | 677 | }; |
671 | 678 | ||
@@ -863,6 +870,7 @@ struct nfs4_create_arg { | |||
863 | const struct iattr * attrs; | 870 | const struct iattr * attrs; |
864 | const struct nfs_fh * dir_fh; | 871 | const struct nfs_fh * dir_fh; |
865 | const u32 * bitmask; | 872 | const u32 * bitmask; |
873 | const struct nfs4_label *label; | ||
866 | }; | 874 | }; |
867 | 875 | ||
868 | struct nfs4_create_res { | 876 | struct nfs4_create_res { |
@@ -870,6 +878,7 @@ struct nfs4_create_res { | |||
870 | const struct nfs_server * server; | 878 | const struct nfs_server * server; |
871 | struct nfs_fh * fh; | 879 | struct nfs_fh * fh; |
872 | struct nfs_fattr * fattr; | 880 | struct nfs_fattr * fattr; |
881 | struct nfs4_label *label; | ||
873 | struct nfs4_change_info dir_cinfo; | 882 | struct nfs4_change_info dir_cinfo; |
874 | }; | 883 | }; |
875 | 884 | ||
@@ -894,6 +903,7 @@ struct nfs4_getattr_res { | |||
894 | struct nfs4_sequence_res seq_res; | 903 | struct nfs4_sequence_res seq_res; |
895 | const struct nfs_server * server; | 904 | const struct nfs_server * server; |
896 | struct nfs_fattr * fattr; | 905 | struct nfs_fattr * fattr; |
906 | struct nfs4_label *label; | ||
897 | }; | 907 | }; |
898 | 908 | ||
899 | struct nfs4_link_arg { | 909 | struct nfs4_link_arg { |
@@ -908,6 +918,7 @@ struct nfs4_link_res { | |||
908 | struct nfs4_sequence_res seq_res; | 918 | struct nfs4_sequence_res seq_res; |
909 | const struct nfs_server * server; | 919 | const struct nfs_server * server; |
910 | struct nfs_fattr * fattr; | 920 | struct nfs_fattr * fattr; |
921 | struct nfs4_label *label; | ||
911 | struct nfs4_change_info cinfo; | 922 | struct nfs4_change_info cinfo; |
912 | struct nfs_fattr * dir_attr; | 923 | struct nfs_fattr * dir_attr; |
913 | }; | 924 | }; |
@@ -925,6 +936,7 @@ struct nfs4_lookup_res { | |||
925 | const struct nfs_server * server; | 936 | const struct nfs_server * server; |
926 | struct nfs_fattr * fattr; | 937 | struct nfs_fattr * fattr; |
927 | struct nfs_fh * fh; | 938 | struct nfs_fh * fh; |
939 | struct nfs4_label *label; | ||
928 | }; | 940 | }; |
929 | 941 | ||
930 | struct nfs4_lookup_root_arg { | 942 | struct nfs4_lookup_root_arg { |
@@ -1367,11 +1379,12 @@ struct nfs_rpc_ops { | |||
1367 | struct dentry *(*try_mount) (int, const char *, struct nfs_mount_info *, | 1379 | struct dentry *(*try_mount) (int, const char *, struct nfs_mount_info *, |
1368 | struct nfs_subversion *); | 1380 | struct nfs_subversion *); |
1369 | int (*getattr) (struct nfs_server *, struct nfs_fh *, | 1381 | int (*getattr) (struct nfs_server *, struct nfs_fh *, |
1370 | struct nfs_fattr *); | 1382 | struct nfs_fattr *, struct nfs4_label *); |
1371 | int (*setattr) (struct dentry *, struct nfs_fattr *, | 1383 | int (*setattr) (struct dentry *, struct nfs_fattr *, |
1372 | struct iattr *); | 1384 | struct iattr *); |
1373 | int (*lookup) (struct inode *, struct qstr *, | 1385 | int (*lookup) (struct inode *, struct qstr *, |
1374 | struct nfs_fh *, struct nfs_fattr *); | 1386 | struct nfs_fh *, struct nfs_fattr *, |
1387 | struct nfs4_label *); | ||
1375 | int (*access) (struct inode *, struct nfs_access_entry *); | 1388 | int (*access) (struct inode *, struct nfs_access_entry *); |
1376 | int (*readlink)(struct inode *, struct page *, unsigned int, | 1389 | int (*readlink)(struct inode *, struct page *, unsigned int, |
1377 | unsigned int); | 1390 | unsigned int); |
diff --git a/include/linux/security.h b/include/linux/security.h index 4686491852a7..a585a9085e46 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/capability.h> | 26 | #include <linux/capability.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/err.h> | 28 | #include <linux/err.h> |
29 | #include <linux/string.h> | ||
29 | 30 | ||
30 | struct linux_binprm; | 31 | struct linux_binprm; |
31 | struct cred; | 32 | struct cred; |
@@ -60,6 +61,9 @@ struct mm_struct; | |||
60 | #define SECURITY_CAP_NOAUDIT 0 | 61 | #define SECURITY_CAP_NOAUDIT 0 |
61 | #define SECURITY_CAP_AUDIT 1 | 62 | #define SECURITY_CAP_AUDIT 1 |
62 | 63 | ||
64 | /* LSM Agnostic defines for sb_set_mnt_opts */ | ||
65 | #define SECURITY_LSM_NATIVE_LABELS 1 | ||
66 | |||
63 | struct ctl_table; | 67 | struct ctl_table; |
64 | struct audit_krule; | 68 | struct audit_krule; |
65 | struct user_namespace; | 69 | struct user_namespace; |
@@ -306,6 +310,15 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
306 | * Parse a string of security data filling in the opts structure | 310 | * Parse a string of security data filling in the opts structure |
307 | * @options string containing all mount options known by the LSM | 311 | * @options string containing all mount options known by the LSM |
308 | * @opts binary data structure usable by the LSM | 312 | * @opts binary data structure usable by the LSM |
313 | * @dentry_init_security: | ||
314 | * Compute a context for a dentry as the inode is not yet available | ||
315 | * since NFSv4 has no label backed by an EA anyway. | ||
316 | * @dentry dentry to use in calculating the context. | ||
317 | * @mode mode used to determine resource type. | ||
318 | * @name name of the last path component used to create file | ||
319 | * @ctx pointer to place the pointer to the resulting context in. | ||
320 | * @ctxlen point to place the length of the resulting context. | ||
321 | * | ||
309 | * | 322 | * |
310 | * Security hooks for inode operations. | 323 | * Security hooks for inode operations. |
311 | * | 324 | * |
@@ -1313,6 +1326,13 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
1313 | * @pages contains the number of pages. | 1326 | * @pages contains the number of pages. |
1314 | * Return 0 if permission is granted. | 1327 | * Return 0 if permission is granted. |
1315 | * | 1328 | * |
1329 | * @ismaclabel: | ||
1330 | * Check if the extended attribute specified by @name | ||
1331 | * represents a MAC label. Returns 1 if name is a MAC | ||
1332 | * attribute otherwise returns 0. | ||
1333 | * @name full extended attribute name to check against | ||
1334 | * LSM as a MAC label. | ||
1335 | * | ||
1316 | * @secid_to_secctx: | 1336 | * @secid_to_secctx: |
1317 | * Convert secid to security context. If secdata is NULL the length of | 1337 | * Convert secid to security context. If secdata is NULL the length of |
1318 | * the result will be returned in seclen, but no secdata will be returned. | 1338 | * the result will be returned in seclen, but no secdata will be returned. |
@@ -1439,10 +1459,16 @@ struct security_operations { | |||
1439 | int (*sb_pivotroot) (struct path *old_path, | 1459 | int (*sb_pivotroot) (struct path *old_path, |
1440 | struct path *new_path); | 1460 | struct path *new_path); |
1441 | int (*sb_set_mnt_opts) (struct super_block *sb, | 1461 | int (*sb_set_mnt_opts) (struct super_block *sb, |
1442 | struct security_mnt_opts *opts); | 1462 | struct security_mnt_opts *opts, |
1463 | unsigned long kern_flags, | ||
1464 | unsigned long *set_kern_flags); | ||
1443 | int (*sb_clone_mnt_opts) (const struct super_block *oldsb, | 1465 | int (*sb_clone_mnt_opts) (const struct super_block *oldsb, |
1444 | struct super_block *newsb); | 1466 | struct super_block *newsb); |
1445 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); | 1467 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); |
1468 | int (*dentry_init_security) (struct dentry *dentry, int mode, | ||
1469 | struct qstr *name, void **ctx, | ||
1470 | u32 *ctxlen); | ||
1471 | |||
1446 | 1472 | ||
1447 | #ifdef CONFIG_SECURITY_PATH | 1473 | #ifdef CONFIG_SECURITY_PATH |
1448 | int (*path_unlink) (struct path *dir, struct dentry *dentry); | 1474 | int (*path_unlink) (struct path *dir, struct dentry *dentry); |
@@ -1590,6 +1616,7 @@ struct security_operations { | |||
1590 | 1616 | ||
1591 | int (*getprocattr) (struct task_struct *p, char *name, char **value); | 1617 | int (*getprocattr) (struct task_struct *p, char *name, char **value); |
1592 | int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size); | 1618 | int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size); |
1619 | int (*ismaclabel) (const char *name); | ||
1593 | int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen); | 1620 | int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen); |
1594 | int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid); | 1621 | int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid); |
1595 | void (*release_secctx) (char *secdata, u32 seclen); | 1622 | void (*release_secctx) (char *secdata, u32 seclen); |
@@ -1725,10 +1752,16 @@ int security_sb_mount(const char *dev_name, struct path *path, | |||
1725 | const char *type, unsigned long flags, void *data); | 1752 | const char *type, unsigned long flags, void *data); |
1726 | int security_sb_umount(struct vfsmount *mnt, int flags); | 1753 | int security_sb_umount(struct vfsmount *mnt, int flags); |
1727 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); | 1754 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); |
1728 | int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); | 1755 | int security_sb_set_mnt_opts(struct super_block *sb, |
1756 | struct security_mnt_opts *opts, | ||
1757 | unsigned long kern_flags, | ||
1758 | unsigned long *set_kern_flags); | ||
1729 | int security_sb_clone_mnt_opts(const struct super_block *oldsb, | 1759 | int security_sb_clone_mnt_opts(const struct super_block *oldsb, |
1730 | struct super_block *newsb); | 1760 | struct super_block *newsb); |
1731 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); | 1761 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); |
1762 | int security_dentry_init_security(struct dentry *dentry, int mode, | ||
1763 | struct qstr *name, void **ctx, | ||
1764 | u32 *ctxlen); | ||
1732 | 1765 | ||
1733 | int security_inode_alloc(struct inode *inode); | 1766 | int security_inode_alloc(struct inode *inode); |
1734 | void security_inode_free(struct inode *inode); | 1767 | void security_inode_free(struct inode *inode); |
@@ -1840,6 +1873,7 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode); | |||
1840 | int security_getprocattr(struct task_struct *p, char *name, char **value); | 1873 | int security_getprocattr(struct task_struct *p, char *name, char **value); |
1841 | int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size); | 1874 | int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size); |
1842 | int security_netlink_send(struct sock *sk, struct sk_buff *skb); | 1875 | int security_netlink_send(struct sock *sk, struct sk_buff *skb); |
1876 | int security_ismaclabel(const char *name); | ||
1843 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); | 1877 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); |
1844 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); | 1878 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); |
1845 | void security_release_secctx(char *secdata, u32 seclen); | 1879 | void security_release_secctx(char *secdata, u32 seclen); |
@@ -2011,7 +2045,9 @@ static inline int security_sb_pivotroot(struct path *old_path, | |||
2011 | } | 2045 | } |
2012 | 2046 | ||
2013 | static inline int security_sb_set_mnt_opts(struct super_block *sb, | 2047 | static inline int security_sb_set_mnt_opts(struct super_block *sb, |
2014 | struct security_mnt_opts *opts) | 2048 | struct security_mnt_opts *opts, |
2049 | unsigned long kern_flags, | ||
2050 | unsigned long *set_kern_flags) | ||
2015 | { | 2051 | { |
2016 | return 0; | 2052 | return 0; |
2017 | } | 2053 | } |
@@ -2035,6 +2071,16 @@ static inline int security_inode_alloc(struct inode *inode) | |||
2035 | static inline void security_inode_free(struct inode *inode) | 2071 | static inline void security_inode_free(struct inode *inode) |
2036 | { } | 2072 | { } |
2037 | 2073 | ||
2074 | static inline int security_dentry_init_security(struct dentry *dentry, | ||
2075 | int mode, | ||
2076 | struct qstr *name, | ||
2077 | void **ctx, | ||
2078 | u32 *ctxlen) | ||
2079 | { | ||
2080 | return -EOPNOTSUPP; | ||
2081 | } | ||
2082 | |||
2083 | |||
2038 | static inline int security_inode_init_security(struct inode *inode, | 2084 | static inline int security_inode_init_security(struct inode *inode, |
2039 | struct inode *dir, | 2085 | struct inode *dir, |
2040 | const struct qstr *qstr, | 2086 | const struct qstr *qstr, |
@@ -2520,6 +2566,11 @@ static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
2520 | return cap_netlink_send(sk, skb); | 2566 | return cap_netlink_send(sk, skb); |
2521 | } | 2567 | } |
2522 | 2568 | ||
2569 | static inline int security_ismaclabel(const char *name) | ||
2570 | { | ||
2571 | return 0; | ||
2572 | } | ||
2573 | |||
2523 | static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 2574 | static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
2524 | { | 2575 | { |
2525 | return -EOPNOTSUPP; | 2576 | return -EOPNOTSUPP; |
diff --git a/security/capability.c b/security/capability.c index 1728d4e375db..d32e16e3c6ae 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -91,7 +91,10 @@ static int cap_sb_pivotroot(struct path *old_path, struct path *new_path) | |||
91 | } | 91 | } |
92 | 92 | ||
93 | static int cap_sb_set_mnt_opts(struct super_block *sb, | 93 | static int cap_sb_set_mnt_opts(struct super_block *sb, |
94 | struct security_mnt_opts *opts) | 94 | struct security_mnt_opts *opts, |
95 | unsigned long kern_flags, | ||
96 | unsigned long *set_kern_flags) | ||
97 | |||
95 | { | 98 | { |
96 | if (unlikely(opts->num_mnt_opts)) | 99 | if (unlikely(opts->num_mnt_opts)) |
97 | return -EOPNOTSUPP; | 100 | return -EOPNOTSUPP; |
@@ -109,6 +112,13 @@ static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | |||
109 | return 0; | 112 | return 0; |
110 | } | 113 | } |
111 | 114 | ||
115 | static int cap_dentry_init_security(struct dentry *dentry, int mode, | ||
116 | struct qstr *name, void **ctx, | ||
117 | u32 *ctxlen) | ||
118 | { | ||
119 | return 0; | ||
120 | } | ||
121 | |||
112 | static int cap_inode_alloc_security(struct inode *inode) | 122 | static int cap_inode_alloc_security(struct inode *inode) |
113 | { | 123 | { |
114 | return 0; | 124 | return 0; |
@@ -816,6 +826,11 @@ static int cap_setprocattr(struct task_struct *p, char *name, void *value, | |||
816 | return -EINVAL; | 826 | return -EINVAL; |
817 | } | 827 | } |
818 | 828 | ||
829 | static int cap_ismaclabel(const char *name) | ||
830 | { | ||
831 | return 0; | ||
832 | } | ||
833 | |||
819 | static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 834 | static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
820 | { | 835 | { |
821 | return -EOPNOTSUPP; | 836 | return -EOPNOTSUPP; |
@@ -931,6 +946,7 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
931 | set_to_cap_if_null(ops, sb_set_mnt_opts); | 946 | set_to_cap_if_null(ops, sb_set_mnt_opts); |
932 | set_to_cap_if_null(ops, sb_clone_mnt_opts); | 947 | set_to_cap_if_null(ops, sb_clone_mnt_opts); |
933 | set_to_cap_if_null(ops, sb_parse_opts_str); | 948 | set_to_cap_if_null(ops, sb_parse_opts_str); |
949 | set_to_cap_if_null(ops, dentry_init_security); | ||
934 | set_to_cap_if_null(ops, inode_alloc_security); | 950 | set_to_cap_if_null(ops, inode_alloc_security); |
935 | set_to_cap_if_null(ops, inode_free_security); | 951 | set_to_cap_if_null(ops, inode_free_security); |
936 | set_to_cap_if_null(ops, inode_init_security); | 952 | set_to_cap_if_null(ops, inode_init_security); |
@@ -1034,6 +1050,7 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
1034 | set_to_cap_if_null(ops, d_instantiate); | 1050 | set_to_cap_if_null(ops, d_instantiate); |
1035 | set_to_cap_if_null(ops, getprocattr); | 1051 | set_to_cap_if_null(ops, getprocattr); |
1036 | set_to_cap_if_null(ops, setprocattr); | 1052 | set_to_cap_if_null(ops, setprocattr); |
1053 | set_to_cap_if_null(ops, ismaclabel); | ||
1037 | set_to_cap_if_null(ops, secid_to_secctx); | 1054 | set_to_cap_if_null(ops, secid_to_secctx); |
1038 | set_to_cap_if_null(ops, secctx_to_secid); | 1055 | set_to_cap_if_null(ops, secctx_to_secid); |
1039 | set_to_cap_if_null(ops, release_secctx); | 1056 | set_to_cap_if_null(ops, release_secctx); |
diff --git a/security/security.c b/security/security.c index a3dce87d1aef..94b35aef6871 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/capability.h> | 14 | #include <linux/capability.h> |
15 | #include <linux/dcache.h> | ||
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
@@ -293,9 +294,12 @@ int security_sb_pivotroot(struct path *old_path, struct path *new_path) | |||
293 | } | 294 | } |
294 | 295 | ||
295 | int security_sb_set_mnt_opts(struct super_block *sb, | 296 | int security_sb_set_mnt_opts(struct super_block *sb, |
296 | struct security_mnt_opts *opts) | 297 | struct security_mnt_opts *opts, |
298 | unsigned long kern_flags, | ||
299 | unsigned long *set_kern_flags) | ||
297 | { | 300 | { |
298 | return security_ops->sb_set_mnt_opts(sb, opts); | 301 | return security_ops->sb_set_mnt_opts(sb, opts, kern_flags, |
302 | set_kern_flags); | ||
299 | } | 303 | } |
300 | EXPORT_SYMBOL(security_sb_set_mnt_opts); | 304 | EXPORT_SYMBOL(security_sb_set_mnt_opts); |
301 | 305 | ||
@@ -324,6 +328,15 @@ void security_inode_free(struct inode *inode) | |||
324 | security_ops->inode_free_security(inode); | 328 | security_ops->inode_free_security(inode); |
325 | } | 329 | } |
326 | 330 | ||
331 | int security_dentry_init_security(struct dentry *dentry, int mode, | ||
332 | struct qstr *name, void **ctx, | ||
333 | u32 *ctxlen) | ||
334 | { | ||
335 | return security_ops->dentry_init_security(dentry, mode, name, | ||
336 | ctx, ctxlen); | ||
337 | } | ||
338 | EXPORT_SYMBOL(security_dentry_init_security); | ||
339 | |||
327 | int security_inode_init_security(struct inode *inode, struct inode *dir, | 340 | int security_inode_init_security(struct inode *inode, struct inode *dir, |
328 | const struct qstr *qstr, | 341 | const struct qstr *qstr, |
329 | const initxattrs initxattrs, void *fs_data) | 342 | const initxattrs initxattrs, void *fs_data) |
@@ -647,6 +660,7 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer | |||
647 | return 0; | 660 | return 0; |
648 | return security_ops->inode_listsecurity(inode, buffer, buffer_size); | 661 | return security_ops->inode_listsecurity(inode, buffer, buffer_size); |
649 | } | 662 | } |
663 | EXPORT_SYMBOL(security_inode_listsecurity); | ||
650 | 664 | ||
651 | void security_inode_getsecid(const struct inode *inode, u32 *secid) | 665 | void security_inode_getsecid(const struct inode *inode, u32 *secid) |
652 | { | 666 | { |
@@ -1047,6 +1061,12 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
1047 | return security_ops->netlink_send(sk, skb); | 1061 | return security_ops->netlink_send(sk, skb); |
1048 | } | 1062 | } |
1049 | 1063 | ||
1064 | int security_ismaclabel(const char *name) | ||
1065 | { | ||
1066 | return security_ops->ismaclabel(name); | ||
1067 | } | ||
1068 | EXPORT_SYMBOL(security_ismaclabel); | ||
1069 | |||
1050 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 1070 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
1051 | { | 1071 | { |
1052 | return security_ops->secid_to_secctx(secid, secdata, seclen); | 1072 | return security_ops->secid_to_secctx(secid, secdata, seclen); |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5c6f2cd2d095..9f8e9b2e717a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #include <linux/syslog.h> | 81 | #include <linux/syslog.h> |
82 | #include <linux/user_namespace.h> | 82 | #include <linux/user_namespace.h> |
83 | #include <linux/export.h> | 83 | #include <linux/export.h> |
84 | #include <linux/security.h> | ||
84 | #include <linux/msg.h> | 85 | #include <linux/msg.h> |
85 | #include <linux/shm.h> | 86 | #include <linux/shm.h> |
86 | 87 | ||
@@ -284,13 +285,14 @@ static void superblock_free_security(struct super_block *sb) | |||
284 | 285 | ||
285 | /* The file system's label must be initialized prior to use. */ | 286 | /* The file system's label must be initialized prior to use. */ |
286 | 287 | ||
287 | static const char *labeling_behaviors[6] = { | 288 | static const char *labeling_behaviors[7] = { |
288 | "uses xattr", | 289 | "uses xattr", |
289 | "uses transition SIDs", | 290 | "uses transition SIDs", |
290 | "uses task SIDs", | 291 | "uses task SIDs", |
291 | "uses genfs_contexts", | 292 | "uses genfs_contexts", |
292 | "not configured for labeling", | 293 | "not configured for labeling", |
293 | "uses mountpoint labeling", | 294 | "uses mountpoint labeling", |
295 | "uses native labeling", | ||
294 | }; | 296 | }; |
295 | 297 | ||
296 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); | 298 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); |
@@ -552,7 +554,9 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, | |||
552 | * labeling information. | 554 | * labeling information. |
553 | */ | 555 | */ |
554 | static int selinux_set_mnt_opts(struct super_block *sb, | 556 | static int selinux_set_mnt_opts(struct super_block *sb, |
555 | struct security_mnt_opts *opts) | 557 | struct security_mnt_opts *opts, |
558 | unsigned long kern_flags, | ||
559 | unsigned long *set_kern_flags) | ||
556 | { | 560 | { |
557 | const struct cred *cred = current_cred(); | 561 | const struct cred *cred = current_cred(); |
558 | int rc = 0, i; | 562 | int rc = 0, i; |
@@ -580,6 +584,12 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
580 | "before the security server is initialized\n"); | 584 | "before the security server is initialized\n"); |
581 | goto out; | 585 | goto out; |
582 | } | 586 | } |
587 | if (kern_flags && !set_kern_flags) { | ||
588 | /* Specifying internal flags without providing a place to | ||
589 | * place the results is not allowed */ | ||
590 | rc = -EINVAL; | ||
591 | goto out; | ||
592 | } | ||
583 | 593 | ||
584 | /* | 594 | /* |
585 | * Binary mount data FS will come through this function twice. Once | 595 | * Binary mount data FS will come through this function twice. Once |
@@ -670,14 +680,21 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
670 | if (strcmp(sb->s_type->name, "proc") == 0) | 680 | if (strcmp(sb->s_type->name, "proc") == 0) |
671 | sbsec->flags |= SE_SBPROC; | 681 | sbsec->flags |= SE_SBPROC; |
672 | 682 | ||
673 | /* Determine the labeling behavior to use for this filesystem type. */ | 683 | if (!sbsec->behavior) { |
674 | rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid); | 684 | /* |
675 | if (rc) { | 685 | * Determine the labeling behavior to use for this |
676 | printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", | 686 | * filesystem type. |
677 | __func__, sb->s_type->name, rc); | 687 | */ |
678 | goto out; | 688 | rc = security_fs_use((sbsec->flags & SE_SBPROC) ? |
689 | "proc" : sb->s_type->name, | ||
690 | &sbsec->behavior, &sbsec->sid); | ||
691 | if (rc) { | ||
692 | printk(KERN_WARNING | ||
693 | "%s: security_fs_use(%s) returned %d\n", | ||
694 | __func__, sb->s_type->name, rc); | ||
695 | goto out; | ||
696 | } | ||
679 | } | 697 | } |
680 | |||
681 | /* sets the context of the superblock for the fs being mounted. */ | 698 | /* sets the context of the superblock for the fs being mounted. */ |
682 | if (fscontext_sid) { | 699 | if (fscontext_sid) { |
683 | rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred); | 700 | rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred); |
@@ -692,6 +709,11 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
692 | * sets the label used on all file below the mountpoint, and will set | 709 | * sets the label used on all file below the mountpoint, and will set |
693 | * the superblock context if not already set. | 710 | * the superblock context if not already set. |
694 | */ | 711 | */ |
712 | if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) { | ||
713 | sbsec->behavior = SECURITY_FS_USE_NATIVE; | ||
714 | *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS; | ||
715 | } | ||
716 | |||
695 | if (context_sid) { | 717 | if (context_sid) { |
696 | if (!fscontext_sid) { | 718 | if (!fscontext_sid) { |
697 | rc = may_context_mount_sb_relabel(context_sid, sbsec, | 719 | rc = may_context_mount_sb_relabel(context_sid, sbsec, |
@@ -723,7 +745,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
723 | } | 745 | } |
724 | 746 | ||
725 | if (defcontext_sid) { | 747 | if (defcontext_sid) { |
726 | if (sbsec->behavior != SECURITY_FS_USE_XATTR) { | 748 | if (sbsec->behavior != SECURITY_FS_USE_XATTR && |
749 | sbsec->behavior != SECURITY_FS_USE_NATIVE) { | ||
727 | rc = -EINVAL; | 750 | rc = -EINVAL; |
728 | printk(KERN_WARNING "SELinux: defcontext option is " | 751 | printk(KERN_WARNING "SELinux: defcontext option is " |
729 | "invalid for this filesystem type\n"); | 752 | "invalid for this filesystem type\n"); |
@@ -980,7 +1003,7 @@ static int superblock_doinit(struct super_block *sb, void *data) | |||
980 | goto out_err; | 1003 | goto out_err; |
981 | 1004 | ||
982 | out: | 1005 | out: |
983 | rc = selinux_set_mnt_opts(sb, &opts); | 1006 | rc = selinux_set_mnt_opts(sb, &opts, 0, NULL); |
984 | 1007 | ||
985 | out_err: | 1008 | out_err: |
986 | security_free_mnt_opts(&opts); | 1009 | security_free_mnt_opts(&opts); |
@@ -1222,6 +1245,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1222 | } | 1245 | } |
1223 | 1246 | ||
1224 | switch (sbsec->behavior) { | 1247 | switch (sbsec->behavior) { |
1248 | case SECURITY_FS_USE_NATIVE: | ||
1249 | break; | ||
1225 | case SECURITY_FS_USE_XATTR: | 1250 | case SECURITY_FS_USE_XATTR: |
1226 | if (!inode->i_op->getxattr) { | 1251 | if (!inode->i_op->getxattr) { |
1227 | isec->sid = sbsec->def_sid; | 1252 | isec->sid = sbsec->def_sid; |
@@ -2515,6 +2540,40 @@ static void selinux_inode_free_security(struct inode *inode) | |||
2515 | inode_free_security(inode); | 2540 | inode_free_security(inode); |
2516 | } | 2541 | } |
2517 | 2542 | ||
2543 | static int selinux_dentry_init_security(struct dentry *dentry, int mode, | ||
2544 | struct qstr *name, void **ctx, | ||
2545 | u32 *ctxlen) | ||
2546 | { | ||
2547 | const struct cred *cred = current_cred(); | ||
2548 | struct task_security_struct *tsec; | ||
2549 | struct inode_security_struct *dsec; | ||
2550 | struct superblock_security_struct *sbsec; | ||
2551 | struct inode *dir = dentry->d_parent->d_inode; | ||
2552 | u32 newsid; | ||
2553 | int rc; | ||
2554 | |||
2555 | tsec = cred->security; | ||
2556 | dsec = dir->i_security; | ||
2557 | sbsec = dir->i_sb->s_security; | ||
2558 | |||
2559 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | ||
2560 | newsid = tsec->create_sid; | ||
2561 | } else { | ||
2562 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
2563 | inode_mode_to_security_class(mode), | ||
2564 | name, | ||
2565 | &newsid); | ||
2566 | if (rc) { | ||
2567 | printk(KERN_WARNING | ||
2568 | "%s: security_transition_sid failed, rc=%d\n", | ||
2569 | __func__, -rc); | ||
2570 | return rc; | ||
2571 | } | ||
2572 | } | ||
2573 | |||
2574 | return security_sid_to_context(newsid, (char **)ctx, ctxlen); | ||
2575 | } | ||
2576 | |||
2518 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | 2577 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, |
2519 | const struct qstr *qstr, char **name, | 2578 | const struct qstr *qstr, char **name, |
2520 | void **value, size_t *len) | 2579 | void **value, size_t *len) |
@@ -2849,7 +2908,10 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
2849 | return; | 2908 | return; |
2850 | } | 2909 | } |
2851 | 2910 | ||
2911 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
2852 | isec->sid = newsid; | 2912 | isec->sid = newsid; |
2913 | isec->initialized = 1; | ||
2914 | |||
2853 | return; | 2915 | return; |
2854 | } | 2916 | } |
2855 | 2917 | ||
@@ -2937,6 +2999,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
2937 | if (rc) | 2999 | if (rc) |
2938 | return rc; | 3000 | return rc; |
2939 | 3001 | ||
3002 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
2940 | isec->sid = newsid; | 3003 | isec->sid = newsid; |
2941 | isec->initialized = 1; | 3004 | isec->initialized = 1; |
2942 | return 0; | 3005 | return 0; |
@@ -5420,6 +5483,11 @@ abort_change: | |||
5420 | return error; | 5483 | return error; |
5421 | } | 5484 | } |
5422 | 5485 | ||
5486 | static int selinux_ismaclabel(const char *name) | ||
5487 | { | ||
5488 | return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0); | ||
5489 | } | ||
5490 | |||
5423 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 5491 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
5424 | { | 5492 | { |
5425 | return security_sid_to_context(secid, secdata, seclen); | 5493 | return security_sid_to_context(secid, secdata, seclen); |
@@ -5562,6 +5630,7 @@ static struct security_operations selinux_ops = { | |||
5562 | .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, | 5630 | .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, |
5563 | .sb_parse_opts_str = selinux_parse_opts_str, | 5631 | .sb_parse_opts_str = selinux_parse_opts_str, |
5564 | 5632 | ||
5633 | .dentry_init_security = selinux_dentry_init_security, | ||
5565 | 5634 | ||
5566 | .inode_alloc_security = selinux_inode_alloc_security, | 5635 | .inode_alloc_security = selinux_inode_alloc_security, |
5567 | .inode_free_security = selinux_inode_free_security, | 5636 | .inode_free_security = selinux_inode_free_security, |
@@ -5657,6 +5726,7 @@ static struct security_operations selinux_ops = { | |||
5657 | .getprocattr = selinux_getprocattr, | 5726 | .getprocattr = selinux_getprocattr, |
5658 | .setprocattr = selinux_setprocattr, | 5727 | .setprocattr = selinux_setprocattr, |
5659 | 5728 | ||
5729 | .ismaclabel = selinux_ismaclabel, | ||
5660 | .secid_to_secctx = selinux_secid_to_secctx, | 5730 | .secid_to_secctx = selinux_secid_to_secctx, |
5661 | .secctx_to_secid = selinux_secctx_to_secid, | 5731 | .secctx_to_secid = selinux_secctx_to_secid, |
5662 | .release_secctx = selinux_release_secctx, | 5732 | .release_secctx = selinux_release_secctx, |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 6d3885165d14..8fd8e18ea340 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -169,6 +169,8 @@ int security_get_allow_unknown(void); | |||
169 | #define SECURITY_FS_USE_GENFS 4 /* use the genfs support */ | 169 | #define SECURITY_FS_USE_GENFS 4 /* use the genfs support */ |
170 | #define SECURITY_FS_USE_NONE 5 /* no labeling support */ | 170 | #define SECURITY_FS_USE_NONE 5 /* no labeling support */ |
171 | #define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */ | 171 | #define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */ |
172 | #define SECURITY_FS_USE_NATIVE 7 /* use native label support */ | ||
173 | #define SECURITY_FS_USE_MAX 7 /* Highest SECURITY_FS_USE_XXX */ | ||
172 | 174 | ||
173 | int security_fs_use(const char *fstype, unsigned int *behavior, | 175 | int security_fs_use(const char *fstype, unsigned int *behavior, |
174 | u32 *sid); | 176 | u32 *sid); |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 9cd9b7c661ec..c8adde3aff8f 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -2168,7 +2168,10 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, | |||
2168 | 2168 | ||
2169 | rc = -EINVAL; | 2169 | rc = -EINVAL; |
2170 | c->v.behavior = le32_to_cpu(buf[0]); | 2170 | c->v.behavior = le32_to_cpu(buf[0]); |
2171 | if (c->v.behavior > SECURITY_FS_USE_NONE) | 2171 | /* Determined at runtime, not in policy DB. */ |
2172 | if (c->v.behavior == SECURITY_FS_USE_MNTPOINT) | ||
2173 | goto out; | ||
2174 | if (c->v.behavior > SECURITY_FS_USE_MAX) | ||
2172 | goto out; | 2175 | goto out; |
2173 | 2176 | ||
2174 | rc = -ENOMEM; | 2177 | rc = -ENOMEM; |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index d52c780bdb78..a7f485bb4e2e 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -3329,6 +3329,16 @@ static void smack_audit_rule_free(void *vrule) | |||
3329 | #endif /* CONFIG_AUDIT */ | 3329 | #endif /* CONFIG_AUDIT */ |
3330 | 3330 | ||
3331 | /** | 3331 | /** |
3332 | * smack_ismaclabel - check if xattr @name references a smack MAC label | ||
3333 | * @name: Full xattr name to check. | ||
3334 | */ | ||
3335 | static int smack_ismaclabel(const char *name) | ||
3336 | { | ||
3337 | return (strcmp(name, XATTR_SMACK_SUFFIX) == 0); | ||
3338 | } | ||
3339 | |||
3340 | |||
3341 | /** | ||
3332 | * smack_secid_to_secctx - return the smack label for a secid | 3342 | * smack_secid_to_secctx - return the smack label for a secid |
3333 | * @secid: incoming integer | 3343 | * @secid: incoming integer |
3334 | * @secdata: destination | 3344 | * @secdata: destination |
@@ -3524,6 +3534,7 @@ struct security_operations smack_ops = { | |||
3524 | .audit_rule_free = smack_audit_rule_free, | 3534 | .audit_rule_free = smack_audit_rule_free, |
3525 | #endif /* CONFIG_AUDIT */ | 3535 | #endif /* CONFIG_AUDIT */ |
3526 | 3536 | ||
3537 | .ismaclabel = smack_ismaclabel, | ||
3527 | .secid_to_secctx = smack_secid_to_secctx, | 3538 | .secid_to_secctx = smack_secid_to_secctx, |
3528 | .secctx_to_secid = smack_secctx_to_secid, | 3539 | .secctx_to_secid = smack_secctx_to_secid, |
3529 | .release_secctx = smack_release_secctx, | 3540 | .release_secctx = smack_release_secctx, |