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 /fs/nfs/nfs4proc.c | |
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
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 529 |
1 files changed, 473 insertions, 56 deletions
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 | ||