Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fs/9p: Implement POSIX ACL permission checking function

The ACL value is fetched as a part of inode initialization
from the server and the permission checking function use the
cached value of the ACL

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>

authored by

Aneesh Kumar K.V and committed by
Eric Van Hensbergen
85ff872d 8e44a080

+186 -22
+13
fs/9p/Kconfig
··· 17 17 Choose Y here to enable persistent, read-only local 18 18 caching support for 9p clients using FS-Cache 19 19 20 + 21 + config 9P_FS_POSIX_ACL 22 + bool "9P POSIX Access Control Lists" 23 + depends on 9P_FS 24 + select FS_POSIX_ACL 25 + help 26 + POSIX Access Control Lists (ACLs) support permissions for users and 27 + groups beyond the owner/group/world scheme. 28 + 29 + To learn more about Access Control Lists, visit the POSIX ACLs for 30 + Linux website <http://acl.bestbits.at/>. 31 + 32 + If you don't know what Access Control Lists are, say N
+1
fs/9p/Makefile
··· 13 13 xattr_user.o 14 14 15 15 9p-$(CONFIG_9P_FSCACHE) += cache.o 16 + 9p-$(CONFIG_9P_FS_POSIX_ACL) += acl.o
+96
fs/9p/acl.c
··· 1 + /* 2 + * Copyright IBM Corporation, 2010 3 + * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms of version 2.1 of the GNU Lesser General Public License 7 + * as published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it would be useful, but 10 + * WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 + * 13 + */ 14 + 15 + #include <linux/module.h> 16 + #include <linux/fs.h> 17 + #include <net/9p/9p.h> 18 + #include <net/9p/client.h> 19 + #include <linux/slab.h> 20 + #include <linux/posix_acl_xattr.h> 21 + #include "xattr.h" 22 + #include "acl.h" 23 + 24 + static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name) 25 + { 26 + ssize_t size; 27 + void *value = NULL; 28 + struct posix_acl *acl = NULL;; 29 + 30 + size = v9fs_fid_xattr_get(fid, name, NULL, 0); 31 + if (size > 0) { 32 + value = kzalloc(size, GFP_NOFS); 33 + if (!value) 34 + return ERR_PTR(-ENOMEM); 35 + size = v9fs_fid_xattr_get(fid, name, value, size); 36 + if (size > 0) { 37 + acl = posix_acl_from_xattr(value, size); 38 + if (IS_ERR(acl)) 39 + goto err_out; 40 + } 41 + } else if (size == -ENODATA || size == 0 || 42 + size == -ENOSYS || size == -EOPNOTSUPP) { 43 + acl = NULL; 44 + } else 45 + acl = ERR_PTR(-EIO); 46 + 47 + err_out: 48 + kfree(value); 49 + return acl; 50 + } 51 + 52 + int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) 53 + { 54 + int retval = 0; 55 + struct posix_acl *pacl, *dacl; 56 + 57 + /* get the default/access acl values and cache them */ 58 + dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT); 59 + pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS); 60 + 61 + if (!IS_ERR(dacl) && !IS_ERR(pacl)) { 62 + set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); 63 + set_cached_acl(inode, ACL_TYPE_ACCESS, pacl); 64 + posix_acl_release(dacl); 65 + posix_acl_release(pacl); 66 + } else 67 + retval = -EIO; 68 + 69 + return retval; 70 + } 71 + 72 + static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type) 73 + { 74 + struct posix_acl *acl; 75 + /* 76 + * 9p Always cache the acl value when 77 + * instantiating the inode (v9fs_inode_from_fid) 78 + */ 79 + acl = get_cached_acl(inode, type); 80 + BUG_ON(acl == ACL_NOT_CACHED); 81 + return acl; 82 + } 83 + 84 + int v9fs_check_acl(struct inode *inode, int mask) 85 + { 86 + struct posix_acl *acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS); 87 + 88 + if (IS_ERR(acl)) 89 + return PTR_ERR(acl); 90 + if (acl) { 91 + int error = posix_acl_permission(inode, acl, mask); 92 + posix_acl_release(acl); 93 + return error; 94 + } 95 + return -EAGAIN; 96 + }
+27
fs/9p/acl.h
··· 1 + /* 2 + * Copyright IBM Corporation, 2010 3 + * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms of version 2.1 of the GNU Lesser General Public License 7 + * as published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it would be useful, but 10 + * WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 + * 13 + */ 14 + #ifndef FS_9P_ACL_H 15 + #define FS_9P_ACL_H 16 + 17 + #ifdef CONFIG_9P_FS_POSIX_ACL 18 + extern int v9fs_get_acl(struct inode *, struct p9_fid *); 19 + extern int v9fs_check_acl(struct inode *inode, int mask); 20 + #else 21 + #define v9fs_check_acl NULL 22 + static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) 23 + { 24 + return 0; 25 + } 26 + #endif 27 + #endif /* FS_9P_XATTR_H */
+9 -1
fs/9p/vfs_inode.c
··· 36 36 #include <linux/sched.h> 37 37 #include <linux/slab.h> 38 38 #include <linux/xattr.h> 39 + #include <linux/posix_acl.h> 39 40 #include <net/9p/9p.h> 40 41 #include <net/9p/client.h> 41 42 ··· 45 44 #include "fid.h" 46 45 #include "cache.h" 47 46 #include "xattr.h" 47 + #include "acl.h" 48 48 49 49 static const struct inode_operations v9fs_dir_inode_operations; 50 50 static const struct inode_operations v9fs_dir_inode_operations_dotu; ··· 502 500 v9fs_vcookie_set_qid(ret, &st->qid); 503 501 v9fs_cache_inode_get_cookie(ret); 504 502 #endif 503 + err = v9fs_get_acl(ret, fid); 504 + if (err) { 505 + iput(ret); 506 + goto error; 507 + } 505 508 kfree(st); 506 509 return ret; 507 510 error: ··· 1966 1959 .getxattr = generic_getxattr, 1967 1960 .removexattr = generic_removexattr, 1968 1961 .listxattr = v9fs_listxattr, 1969 - 1962 + .check_acl = v9fs_check_acl, 1970 1963 }; 1971 1964 1972 1965 static const struct inode_operations v9fs_dir_inode_operations = { ··· 1993 1986 .getxattr = generic_getxattr, 1994 1987 .removexattr = generic_removexattr, 1995 1988 .listxattr = v9fs_listxattr, 1989 + .check_acl = v9fs_check_acl, 1996 1990 }; 1997 1991 1998 1992 static const struct inode_operations v9fs_symlink_inode_operations = {
+8 -1
fs/9p/vfs_super.c
··· 46 46 #include "v9fs_vfs.h" 47 47 #include "fid.h" 48 48 #include "xattr.h" 49 + #include "acl.h" 49 50 50 51 static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; 51 52 ··· 88 87 89 88 sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC | 90 89 MS_NOATIME; 90 + 91 + #ifdef CONFIG_9P_FS_POSIX_ACL 92 + sb->s_flags |= MS_POSIXACL; 93 + #endif 91 94 92 95 save_mount_options(sb, data); 93 96 } ··· 154 149 goto release_sb; 155 150 } 156 151 sb->s_root = root; 157 - 158 152 if (v9fs_proto_dotl(v9ses)) { 159 153 struct p9_stat_dotl *st = NULL; 160 154 st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); ··· 178 174 p9stat_free(st); 179 175 kfree(st); 180 176 } 177 + retval = v9fs_get_acl(inode, fid); 178 + if (retval) 179 + goto release_sb; 181 180 182 181 v9fs_fid_add(root, fid); 183 182
+28 -20
fs/9p/xattr.c
··· 21 21 #include "fid.h" 22 22 #include "xattr.h" 23 23 24 - /* 25 - * v9fs_xattr_get() 26 - * 27 - * Copy an extended attribute into the buffer 28 - * provided, or compute the buffer size required. 29 - * Buffer is NULL to compute the size of the buffer required. 30 - * 31 - * Returns a negative error number on failure, or the number of bytes 32 - * used / required on success. 33 - */ 34 - ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name, 35 - void *buffer, size_t buffer_size) 24 + ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name, 25 + void *buffer, size_t buffer_size) 36 26 { 37 27 ssize_t retval; 38 28 int msize, read_count; 39 29 u64 offset = 0, attr_size; 40 - struct p9_fid *fid, *attr_fid; 41 - 42 - P9_DPRINTK(P9_DEBUG_VFS, "%s: name = %s value_len = %zu\n", 43 - __func__, name, buffer_size); 44 - 45 - fid = v9fs_fid_lookup(dentry); 46 - if (IS_ERR(fid)) 47 - return PTR_ERR(fid); 30 + struct p9_fid *attr_fid; 48 31 49 32 attr_fid = p9_client_xattrwalk(fid, name, &attr_size); 50 33 if (IS_ERR(attr_fid)) { ··· 69 86 p9_client_clunk(attr_fid); 70 87 return retval; 71 88 89 + } 90 + 91 + 92 + /* 93 + * v9fs_xattr_get() 94 + * 95 + * Copy an extended attribute into the buffer 96 + * provided, or compute the buffer size required. 97 + * Buffer is NULL to compute the size of the buffer required. 98 + * 99 + * Returns a negative error number on failure, or the number of bytes 100 + * used / required on success. 101 + */ 102 + ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name, 103 + void *buffer, size_t buffer_size) 104 + { 105 + struct p9_fid *fid; 106 + 107 + P9_DPRINTK(P9_DEBUG_VFS, "%s: name = %s value_len = %zu\n", 108 + __func__, name, buffer_size); 109 + fid = v9fs_fid_lookup(dentry); 110 + if (IS_ERR(fid)) 111 + return PTR_ERR(fid); 112 + 113 + return v9fs_fid_xattr_get(fid, name, buffer, buffer_size); 72 114 } 73 115 74 116 /*
+4
fs/9p/xattr.h
··· 15 15 #define FS_9P_XATTR_H 16 16 17 17 #include <linux/xattr.h> 18 + #include <net/9p/9p.h> 19 + #include <net/9p/client.h> 18 20 19 21 extern const struct xattr_handler *v9fs_xattr_handlers[]; 20 22 extern struct xattr_handler v9fs_xattr_user_handler; 21 23 24 + extern ssize_t v9fs_fid_xattr_get(struct p9_fid *, const char *, 25 + void *, size_t); 22 26 extern ssize_t v9fs_xattr_get(struct dentry *, const char *, 23 27 void *, size_t); 24 28 extern int v9fs_xattr_set(struct dentry *, const char *,