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/inode.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/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 109 |
1 files changed, 97 insertions, 12 deletions
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))) |