aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid P. Quigley <dpquigl@tycho.nsa.gov>2008-02-05 01:29:39 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-05 12:44:20 -0500
commit42492594043d621a7910ff5877c3eb9202870b45 (patch)
tree9188d112c019a189606847dc1d90ccc63c1bacf2
parent3729145821e3088a0c3c4183037fde356204bf97 (diff)
VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
This patch modifies the interface to inode_getsecurity to have the function return a buffer containing the security blob and its length via parameters instead of relying on the calling function to give it an appropriately sized buffer. Security blobs obtained with this function should be freed using the release_secctx LSM hook. This alleviates the problem of the caller having to guess a length and preallocate a buffer for this function allowing it to be used elsewhere for Labeled NFS. The patch also removed the unused err parameter. The conversion is similar to the one performed by Al Viro for the security_getprocattr hook. Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov> Cc: Stephen Smalley <sds@tycho.nsa.gov> Cc: Chris Wright <chrisw@sous-sol.org> Acked-by: James Morris <jmorris@namei.org> Acked-by: Serge Hallyn <serue@us.ibm.com> Cc: Casey Schaufler <casey@schaufler-ca.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/xattr.c30
-rw-r--r--include/linux/security.h21
-rw-r--r--include/linux/xattr.h1
-rw-r--r--mm/shmem.c3
-rw-r--r--security/dummy.c2
-rw-r--r--security/security.c4
-rw-r--r--security/selinux/hooks.c43
7 files changed, 57 insertions, 47 deletions
diff --git a/fs/xattr.c b/fs/xattr.c
index 6645b7313b33..1858552a6a1a 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -105,6 +105,33 @@ out:
105EXPORT_SYMBOL_GPL(vfs_setxattr); 105EXPORT_SYMBOL_GPL(vfs_setxattr);
106 106
107ssize_t 107ssize_t
108xattr_getsecurity(struct inode *inode, const char *name, void *value,
109 size_t size)
110{
111 void *buffer = NULL;
112 ssize_t len;
113
114 if (!value || !size) {
115 len = security_inode_getsecurity(inode, name, &buffer, false);
116 goto out_noalloc;
117 }
118
119 len = security_inode_getsecurity(inode, name, &buffer, true);
120 if (len < 0)
121 return len;
122 if (size < len) {
123 len = -ERANGE;
124 goto out;
125 }
126 memcpy(value, buffer, len);
127out:
128 security_release_secctx(buffer, len);
129out_noalloc:
130 return len;
131}
132EXPORT_SYMBOL_GPL(xattr_getsecurity);
133
134ssize_t
108vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size) 135vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
109{ 136{
110 struct inode *inode = dentry->d_inode; 137 struct inode *inode = dentry->d_inode;
@@ -126,8 +153,7 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
126 if (!strncmp(name, XATTR_SECURITY_PREFIX, 153 if (!strncmp(name, XATTR_SECURITY_PREFIX,
127 XATTR_SECURITY_PREFIX_LEN)) { 154 XATTR_SECURITY_PREFIX_LEN)) {
128 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; 155 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
129 int ret = security_inode_getsecurity(inode, suffix, value, 156 int ret = xattr_getsecurity(inode, suffix, value, size);
130 size, error);
131 /* 157 /*
132 * Only overwrite the return value if a security module 158 * Only overwrite the return value if a security module
133 * is actually active. 159 * is actually active.
diff --git a/include/linux/security.h b/include/linux/security.h
index d24974262dc6..9d289e726fd8 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -423,15 +423,12 @@ struct request_sock;
423 * identified by @name for @dentry. 423 * identified by @name for @dentry.
424 * Return 0 if permission is granted. 424 * Return 0 if permission is granted.
425 * @inode_getsecurity: 425 * @inode_getsecurity:
426 * Copy the extended attribute representation of the security label 426 * Retrieve a copy of the extended attribute representation of the
427 * associated with @name for @inode into @buffer. @buffer may be 427 * security label associated with @name for @inode via @buffer. Note that
428 * NULL to request the size of the buffer required. @size indicates 428 * @name is the remainder of the attribute name after the security prefix
429 * the size of @buffer in bytes. Note that @name is the remainder 429 * has been removed. @alloc is used to specify of the call should return a
430 * of the attribute name after the security. prefix has been removed. 430 * value via the buffer or just the value length Return size of buffer on
431 * @err is the return value from the preceding fs getxattr call, 431 * success.
432 * and can be used by the security module to determine whether it
433 * should try and canonicalize the attribute value.
434 * Return number of bytes used/required on success.
435 * @inode_setsecurity: 432 * @inode_setsecurity:
436 * Set the security label associated with @name for @inode from the 433 * Set the security label associated with @name for @inode from the
437 * extended attribute value @value. @size indicates the size of the 434 * extended attribute value @value. @size indicates the size of the
@@ -1304,7 +1301,7 @@ struct security_operations {
1304 int (*inode_removexattr) (struct dentry *dentry, char *name); 1301 int (*inode_removexattr) (struct dentry *dentry, char *name);
1305 int (*inode_need_killpriv) (struct dentry *dentry); 1302 int (*inode_need_killpriv) (struct dentry *dentry);
1306 int (*inode_killpriv) (struct dentry *dentry); 1303 int (*inode_killpriv) (struct dentry *dentry);
1307 int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err); 1304 int (*inode_getsecurity)(const struct inode *inode, const char *name, void **buffer, bool alloc);
1308 int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags); 1305 int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
1309 int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size); 1306 int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size);
1310 1307
@@ -1565,7 +1562,7 @@ int security_inode_listxattr(struct dentry *dentry);
1565int security_inode_removexattr(struct dentry *dentry, char *name); 1562int security_inode_removexattr(struct dentry *dentry, char *name);
1566int security_inode_need_killpriv(struct dentry *dentry); 1563int security_inode_need_killpriv(struct dentry *dentry);
1567int security_inode_killpriv(struct dentry *dentry); 1564int security_inode_killpriv(struct dentry *dentry);
1568int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err); 1565int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
1569int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags); 1566int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
1570int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size); 1567int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
1571int security_file_permission(struct file *file, int mask); 1568int security_file_permission(struct file *file, int mask);
@@ -1967,7 +1964,7 @@ static inline int security_inode_killpriv(struct dentry *dentry)
1967 return cap_inode_killpriv(dentry); 1964 return cap_inode_killpriv(dentry);
1968} 1965}
1969 1966
1970static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err) 1967static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
1971{ 1968{
1972 return -EOPNOTSUPP; 1969 return -EOPNOTSUPP;
1973} 1970}
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index def131a5ac70..df6b95d2218e 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -46,6 +46,7 @@ struct xattr_handler {
46 size_t size, int flags); 46 size_t size, int flags);
47}; 47};
48 48
49ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
49ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t); 50ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
50ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); 51ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
51int vfs_setxattr(struct dentry *, char *, void *, size_t, int); 52int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
diff --git a/mm/shmem.c b/mm/shmem.c
index ee9024483f60..0f246c44a574 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1955,8 +1955,7 @@ static int shmem_xattr_security_get(struct inode *inode, const char *name,
1955{ 1955{
1956 if (strcmp(name, "") == 0) 1956 if (strcmp(name, "") == 0)
1957 return -EINVAL; 1957 return -EINVAL;
1958 return security_inode_getsecurity(inode, name, buffer, size, 1958 return xattr_getsecurity(inode, name, buffer, size);
1959 -EOPNOTSUPP);
1960} 1959}
1961 1960
1962static int shmem_xattr_security_set(struct inode *inode, const char *name, 1961static int shmem_xattr_security_set(struct inode *inode, const char *name,
diff --git a/security/dummy.c b/security/dummy.c
index 48d4b0a52737..c505122e22db 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -402,7 +402,7 @@ static int dummy_inode_killpriv(struct dentry *dentry)
402 return 0; 402 return 0;
403} 403}
404 404
405static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err) 405static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
406{ 406{
407 return -EOPNOTSUPP; 407 return -EOPNOTSUPP;
408} 408}
diff --git a/security/security.c b/security/security.c
index ca475ca206e4..b6c57a6b2ff5 100644
--- a/security/security.c
+++ b/security/security.c
@@ -493,11 +493,11 @@ int security_inode_killpriv(struct dentry *dentry)
493 return security_ops->inode_killpriv(dentry); 493 return security_ops->inode_killpriv(dentry);
494} 494}
495 495
496int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err) 496int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
497{ 497{
498 if (unlikely(IS_PRIVATE(inode))) 498 if (unlikely(IS_PRIVATE(inode)))
499 return 0; 499 return 0;
500 return security_ops->inode_getsecurity(inode, name, buffer, size, err); 500 return security_ops->inode_getsecurity(inode, name, buffer, alloc);
501} 501}
502 502
503int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) 503int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index be6de0b8734f..e5ed07510309 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -136,32 +136,6 @@ static DEFINE_SPINLOCK(sb_security_lock);
136 136
137static struct kmem_cache *sel_inode_cache; 137static struct kmem_cache *sel_inode_cache;
138 138
139/* Return security context for a given sid or just the context
140 length if the buffer is null or length is 0 */
141static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
142{
143 char *context;
144 unsigned len;
145 int rc;
146
147 rc = security_sid_to_context(sid, &context, &len);
148 if (rc)
149 return rc;
150
151 if (!buffer || !size)
152 goto getsecurity_exit;
153
154 if (size < len) {
155 len = -ERANGE;
156 goto getsecurity_exit;
157 }
158 memcpy(buffer, context, len);
159
160getsecurity_exit:
161 kfree(context);
162 return len;
163}
164
165/** 139/**
166 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled 140 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
167 * 141 *
@@ -2675,14 +2649,27 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2675 * 2649 *
2676 * Permission check is handled by selinux_inode_getxattr hook. 2650 * Permission check is handled by selinux_inode_getxattr hook.
2677 */ 2651 */
2678static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err) 2652static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
2679{ 2653{
2654 u32 size;
2655 int error;
2656 char *context = NULL;
2680 struct inode_security_struct *isec = inode->i_security; 2657 struct inode_security_struct *isec = inode->i_security;
2681 2658
2682 if (strcmp(name, XATTR_SELINUX_SUFFIX)) 2659 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2683 return -EOPNOTSUPP; 2660 return -EOPNOTSUPP;
2684 2661
2685 return selinux_getsecurity(isec->sid, buffer, size); 2662 error = security_sid_to_context(isec->sid, &context, &size);
2663 if (error)
2664 return error;
2665 error = size;
2666 if (alloc) {
2667 *buffer = context;
2668 goto out_nofree;
2669 }
2670 kfree(context);
2671out_nofree:
2672 return error;
2686} 2673}
2687 2674
2688static int selinux_inode_setsecurity(struct inode *inode, const char *name, 2675static int selinux_inode_setsecurity(struct inode *inode, const char *name,