Permit filesystem local caching
Subsystems (64)
David Howells
maintainercover Permit filesystem local caching
These patches add local caching for network filesystems such as NFS.
The patches can roughly be broken down into a number of sets:
(*) 01-keys-inc-payload.diff
(*) 02-keys-search-keyring.diff
(*) 03-keys-callout-blob.diff
Three patches to the keyring code made to help the CIFS people. Included because of patches 05-08.
(*) 04-keys-get-label.diff
A patch to allow the security label of a key to be retrieved. Included because of patches 05-08.
(*) 05-security-current-fsugid.diff
(*) 06-security-separate-task-bits.diff
(*) 07-security-subjective.diff
(*) 08-security-secctx2secid.diff
(*) 09-security-additional-classes.diff
(*) 10-security-kernel_service-class.diff
(*) 11-security-kernel-service.diff
Patches to permit the subjective security of a task to be overridden. All the security details in task_struct are decanted into a new struct that task_struct then has two pointers two: one that defines the objective security of that task (how other tasks may affect it) and one that defines the subjective security (how it may affect other objects).
Note that I have dropped the idea of struct cred for the moment. With the amount of stuff that was excluded from it, it wasn't actually any use to me. However, it can be added later.
Required for cachefiles.
(*) 12-release-page.diff
(*) 13-fscache-page-flags.diff
(*) 14-add_wait_queue_tail.diff
(*) 15-fscache.diff
Patches to provide a local caching facility for network filesystems.
(*) 16-cachefiles-ia64.diff
(*) 17-cachefiles-ext3-f_mapping.diff
(*) 18-cachefiles-write.diff
(*) 19-cachefiles-monitor.diff
(*) 20-cachefiles-export.diff
(*) 21-cachefiles.diff
Patches to provide a local cache in a directory of an already mounted filesystem.
(*) 22-nfs-memleak.diff
(*) 23-fscache-nfs.diff
(*) 24-fscache-nfs-mount.diff
(*) 25-fscache-nfs-display.diff
(*) 26-fscache-nfs-persb.diff
Patches to provide NFS with local caching. The fifth of these patches makes caching configurable per superblock.
This release is mainly for the security guys (esp Stephen and Casey) to have a look at to see if they are happy with the security stuff.
The SELinux base code will also need updating to have the security class, lest the following error appear in dmesg:
context_struct_compute_av: unrecognized class 69
I know Nick Piggin has a couple of issues still, but I'll look again at those next.
Andrew, Linus, can you please hold off on taking these patches for the moment.
--
A tarball of the patches is available at:
http://people.redhat.com/~dhowells/fscache/patches/nfs+fscache-26.tar.bz2
To use this version of CacheFiles, the cachefilesd-0.9 is also required. It is available as an SRPM:
http://people.redhat.com/~dhowells/fscache/cachefilesd-0.9-1.fc7.src.rpm
Or as individual bits:
http://people.redhat.com/~dhowells/fscache/cachefilesd-0.9.tar.bz2
http://people.redhat.com/~dhowells/fscache/cachefilesd.fc
http://people.redhat.com/~dhowells/fscache/cachefilesd.if
http://people.redhat.com/~dhowells/fscache/cachefilesd.te
http://people.redhat.com/~dhowells/fscache/cachefilesd.spec
The .fc, .if and .te files are for manipulating SELinux.
David
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 1/26 KEYS: Increase the payload size when instantiating a key
Increase the size of a payload that can be used to instantiate a key in add_key() and keyctl_instantiate_key(). This permits huge CIFS SPNEGO blobs to be passed around. The limit is raised to 1MB. If kmalloc() can't allocate a buffer of sufficient size, vmalloc() will be tried instead.
---
security/keys/keyctl.c | 38 ++++++++++++++++++++++++++++++-------- 1 files changed, 30 insertions(+), 8 deletions(-)
security/keys/keyctl.c +30 -8
@@ -19,6 +19,7 @@#include <linux/capability.h> #include <linux/string.h> #include <linux/err.h> +#include <linux/vmalloc.h> #include <asm/uaccess.h> #include "internal.h"
@@ -62,9 +63,10 @@ asmlinkage long sys_add_key(const char __user *_type,char type[32 ], *description;void *payload;long ret; +bool vm; ret = -EINVAL ; -if (plen >32767 ) +if (plen >1024 *1024 -1 ) goto error;/* draw all the data into kernel space */
@@ -81,11 +83,18 @@ asmlinkage long sys_add_key(const char __user *_type,/* pull the payload in if one was supplied */ payload =NULL ; + vm = false;if (_payload) { ret = -ENOMEM ; payload =kmalloc (plen,GFP_KERNEL ); -if (!payload) - goto error2; +if (!payload) { +if (plen <=PAGE_SIZE ) + goto error2; + vm = true; + payload =vmalloc (plen); +if (!payload) + goto error2; + } ret = -EFAULT ;if (copy_from_user (payload, _payload, plen) !=0 )
@@ -113,7 +122,10 @@ asmlinkage long sys_add_key(const char __user *_type,key_ref_put (keyring_ref); error3: -kfree (payload); +if (!vm) +kfree (payload); +else +vfree (payload); error2:kfree (description); error:
@@ -821,9 +833,10 @@ long keyctl_instantiate_key(key_serial_t id,key_ref_t keyring_ref;void *payload;long ret; +bool vm = false; ret = -EINVAL ; -if (plen >32767 ) +if (plen >1024 *1024 -1 ) goto error;/* the appropriate instantiation authorisation key must have been
@@ -843,8 +856,14 @@ long keyctl_instantiate_key(key_serial_t id,if (_payload) { ret = -ENOMEM ; payload =kmalloc (plen,GFP_KERNEL ); -if (!payload) - goto error; +if (!payload) { +if (plen <=PAGE_SIZE ) + goto error; + vm = true; + payload =vmalloc (plen); +if (!payload) + goto error; + } ret = -EFAULT ;if (copy_from_user (payload, _payload, plen) !=0 )
@@ -877,7 +896,10 @@ long keyctl_instantiate_key(key_serial_t id, } error2: -kfree (payload); +if (!vm) +kfree (payload); +else +vfree (payload); error:return ret;
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 2/26 KEYS: Check starting keyring as part of search
In reply to David HowellsCheck the starting keyring as part of the search to (a) see if that is what we're searching for, and (b) to check it is still valid for searching.
The scenario: User in process A does things that cause things to be created in its process session keyring. The user then does an su to another user and starts a new process, B. The two processes now share the same process session keyring.
Process B does an NFS access which results in an upcall to gssd. When gssd attempts to instantiate the context key (to be linked into the process session keyring), it is denied access even though it has an authorization key.
The order of calls is:
keyctl_instantiate_key()
lookup_user_key() (the default: case)
search_process_keyrings(current)
search_process_keyrings(rka->context) (recursive call)
keyring_search_aux()
keyring_search_aux() verifies the keys and keyrings underneath the top-level keyring it is given, but that top-level keyring is neither fully validated nor checked to see if it is the thing being searched for.
This patch changes keyring_search_aux() to:
1) do more validation on the top keyring it is given and
2) check whether that top-level keyring is the thing being searched for
---
security/keys/keyring.c | 35 +++++++++++++++++++++++++++++++---- 1 files changed, 31 insertions(+), 4 deletions(-)
security/keys/keyring.c +31 -4
@@ -292,7 +292,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,struct keyring_list *keylist;struct timespec now; -unsigned long possessed; +unsigned long possessed, kflags;struct key *keyring, *key;key_ref_t key_ref;long err;
@@ -318,6 +318,32 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, now =current_kernel_time (); err = -EAGAIN ; sp =0 ; + +/* firstly we should check to see if this top-level keyring is what we +* are looking for */ + key_ref =ERR_PTR (-EAGAIN ); + kflags = keyring->flags; +if (keyring->type == type &&match (keyring, description)) { + key = keyring; + +/* check it isn't negative and hasn't expired or been +* revoked */ +if (kflags & (1 <<KEY_FLAG_REVOKED )) + goto error_2; +if (key->expiry && now.tv_sec >= key->expiry) + goto error_2; + key_ref =ERR_PTR (-ENOKEY ); +if (kflags & (1 <<KEY_FLAG_NEGATIVE )) + goto error_2; + goto found; + } + +/* otherwise, the top keyring must not be revoked, expired, or +* negatively instantiated if we are to search it */ + key_ref =ERR_PTR (-EAGAIN ); +if (kflags & ((1 <<KEY_FLAG_REVOKED ) | (1 <<KEY_FLAG_NEGATIVE )) || + (keyring->expiry && now.tv_sec >= keyring->expiry)) + goto error_2;/* start processing a new keyring */ descend:
@@ -331,13 +357,14 @@ descend:/* iterate through the keys in this keyring first */ for (kix =0 ; kix < keylist->nkeys; kix++) { key = keylist->keys[kix]; + kflags = key->flags;/* ignore keys not of this type */ if (key->type != type)continue ;/* skip revoked keys and expired keys */ -if (test_bit (KEY_FLAG_REVOKED , &key->flags)) +if (kflags & (1 <<KEY_FLAG_REVOKED ))continue ;if (key->expiry && now.tv_sec >= key->expiry)
@@ -352,8 +379,8 @@ descend: context, KEY_SEARCH) < 0)continue ; -/* we set a different error code if we find a negative key */ -if (test_bit (KEY_FLAG_NEGATIVE , &key->flags)) { +/* we set a different error code if we pass a negative key */ +if (kflags & (1 <<KEY_FLAG_NEGATIVE )) { err = -ENOKEY ;continue ; }
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 3/26 KEYS: Allow the callout data to be passed as a blob rather than a string
In reply to David HowellsAllow the callout data to be passed as a blob rather than a string for internal kernel services that call any request_key_*() interface other than request_key(). request_key() itself still takes a NUL-terminated string.
The functions that change are:
request_key_with_auxdata()
request_key_async()
request_key_async_with_auxdata()
---
Documentation/keys-request-key.txt | 11 +++++--- Documentation/keys.txt | 14 +++++++--- include/linux/key.h | 9 ++++--- security/keys/internal.h | 9 ++++--- security/keys/keyctl.c | 7 ++++- security/keys/request_key.c | 49 ++++++++++++++++++++++-------------- security/keys/request_key_auth.c | 12 +++++---- 7 files changed, 70 insertions(+), 41 deletions(-)
Documentation/keys-request-key.txt +7 -4
@@ -11,26 +11,29 @@ request_key*(): struct key *request_key(const struct key_type *type, const char *description, - const char *callout_string); + const char *callout_info); or: struct key *request_key_with_auxdata(const struct key_type *type, const char *description, - const char *callout_string, + const char *callout_info, + size_t callout_len, void *aux); or: struct key *request_key_async(const struct key_type *type, const char *description, - const char *callout_string); + const char *callout_info, + size_t callout_len); or: struct key *request_key_async_with_auxdata(const struct key_type *type, const char *description, - const char *callout_string, + const char *callout_info, + size_t callout_len, void *aux); Or by userspace invoking the request_key system call:
Documentation/keys.txt +9 -5
@@ -771,7 +771,7 @@ payload contents" for more information. struct key *request_key(const struct key_type *type, const char *description, - const char *callout_string); + const char *callout_info); This is used to request a key or keyring with a description that matches the description specified according to the key type's match function. This
@@ -793,24 +793,28 @@ payload contents" for more information. struct key *request_key_with_auxdata(const struct key_type *type, const char *description, - const char *callout_string, + const void *callout_info, + size_t callout_len, void *aux); This is identical to request_key(), except that the auxiliary data is - passed to the key_type->request_key() op if it exists. + passed to the key_type->request_key() op if it exists, and the callout_info + is a blob of length callout_len, if given (the length may be 0). (*) A key can be requested asynchronously by calling one of: struct key *request_key_async(const struct key_type *type, const char *description, - const char *callout_string); + const void *callout_info, + size_t callout_len); or: struct key *request_key_async_with_auxdata(const struct key_type *type, const char *description, - const char *callout_string, + const char *callout_info, + size_t callout_len, void *aux); which are asynchronous equivalents of request_key() and
include/linux/key.h +6 -3
@@ -208,16 +208,19 @@ extern struct key *request_key(struct key_type *type,extern struct key *request_key_with_auxdata (struct key_type *type,const char *description, -const char *callout_info, +const void *callout_info, +size_t callout_len,void *aux);extern struct key *request_key_async (struct key_type *type,const char *description, -const char *callout_info); +const void *callout_info, +size_t callout_len);extern struct key *request_key_async_with_auxdata (struct key_type *type,const char *description, -const char *callout_info, +const void *callout_info, +size_t callout_len,void *aux);extern int wait_for_key_construction (struct key *key,bool intr);
security/keys/internal.h +6 -3
@@ -109,7 +109,8 @@ extern int install_process_keyring(struct task_struct *tsk);extern struct key *request_key_and_link (struct key_type *type,const char *description, -const char *callout_info, +const void *callout_info, +size_t callout_len,void *aux,struct key *dest_keyring,unsigned long flags);
@@ -120,13 +121,15 @@ extern struct key *request_key_and_link(struct key_type *type,struct request_key_auth {struct key *target_key;struct task_struct *context; -char *callout_info; +void *callout_info; +size_t callout_len;pid_t pid; };extern struct key_type key_type_request_key_auth;extern struct key *request_key_auth_new (struct key *target, -const char *callout_info); +const void *callout_info, +size_t callout_len);extern struct key *key_get_instantiation_authkey (key_serial_t target_id);
security/keys/keyctl.c +5 -2
@@ -152,6 +152,7 @@ asmlinkage long sys_request_key(const char __user *_type,struct key_type *ktype;struct key *key;key_ref_t dest_ref; +size_t callout_len;char type[32 ], *description, *callout_info;long ret;
@@ -169,12 +170,14 @@ asmlinkage long sys_request_key(const char __user *_type,/* pull the callout info into kernel space */ callout_info =NULL ; + callout_len =0 ;if (_callout_info) { callout_info =strndup_user (_callout_info,PAGE_SIZE );if (IS_ERR (callout_info)) { ret =PTR_ERR (callout_info); goto error2; } + callout_len =strlen (callout_info); }/* get the destination keyring if specified */
@@ -195,8 +198,8 @@ asmlinkage long sys_request_key(const char __user *_type, }/* do the search */ - key =request_key_and_link (ktype, description, callout_info,NULL , -key_ref_to_ptr (dest_ref), + key =request_key_and_link (ktype, description, callout_info, + callout_len,NULL ,key_ref_to_ptr (dest_ref),KEY_ALLOC_IN_QUOTA );if (IS_ERR (key)) { ret =PTR_ERR (key);
security/keys/request_key.c +30 -19
130 lines not on this page · raw message
security/keys/request_key_auth.c +7 -5
@@ -61,7 +61,7 @@ static void request_key_auth_describe(const struct key *key,seq_puts (m,"key:" );seq_puts (m, key->description); -seq_printf (m," pid:%d ci:%zu" , rka->pid,strlen (rka->callout_info)); +seq_printf (m," pid:%d ci:%zu" , rka->pid, rka->callout_len); }/* end request_key_auth_describe() */
@@ -77,7 +77,7 @@ static long request_key_auth_read(const struct key *key,size_t datalen;long ret; - datalen =strlen (rka->callout_info); + datalen = rka->callout_len; ret = datalen;/* we can return the data as is */
@@ -137,7 +137,8 @@ static void request_key_auth_destroy(struct key *key)* create an authorisation token for /sbin/request-key or whoever to gain * access to the caller's security data */ -struct key *request_key_auth_new (struct key *target,const char *callout_info) +struct key *request_key_auth_new (struct key *target,const void *callout_info, +size_t callout_len) {struct request_key_auth *rka, *irka;struct key *authkey =NULL ;
@@ -152,7 +153,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)kleave (" = -ENOMEM" );return ERR_PTR (-ENOMEM ); } - rka->callout_info =kmalloc (strlen (callout_info) +1 ,GFP_KERNEL ); + rka->callout_info =kmalloc (callout_len,GFP_KERNEL );if (!rka->callout_info) {kleave (" = -ENOMEM" );kfree (rka);
@@ -186,7 +187,8 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) } rka->target_key =key_get (target); -strcpy (rka->callout_info, callout_info); +memcpy (rka->callout_info, callout_info, callout_len); + rka->callout_len = callout_len;/* allocate the auth key */ sprintf (desc,"%x" , target->serial);
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 4/26 KEYS: Add keyctl function to get a security label
In reply to David HowellsAdd a keyctl() function to get the security label of a key.
The following is added to Documentation/keys.txt:
(*) Get the LSM security context attached to a key.
long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
size_t buflen)
This function returns a string that represents the LSM security context attached to a key in the buffer provided.
Unless there's an error, it always returns the amount of data it could produce, even if that's too big for the buffer, but it won't copy more than requested to userspace. If the buffer pointer is NULL then no copy will take place.
A NUL character is included at the end of the string if the buffer is sufficiently big. This is included in the returned count. If no LSM is in force then an empty string will be returned.
A process must have view permission on the key for this function to be successful.
---
Documentation/keys.txt | 21 +++++++++++++++ include/linux/keyctl.h | 1 + include/linux/security.h | 20 +++++++++++++- security/dummy.c | 8 ++++++ security/keys/compat.c | 3 ++ security/keys/keyctl.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++ security/security.c | 5 +++ security/selinux/hooks.c | 21 +++++++++++++-- 8 files changed, 141 insertions(+), 4 deletions(-)
Documentation/keys.txt +21 -0
@@ -711,6 +711,27 @@ The keyctl syscall functions are: The assumed authoritative key is inherited across fork and exec. + (*) Get the LSM security context attached to a key. + + long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer, + size_t buflen) + + This function returns a string that represents the LSM security context + attached to a key in the buffer provided. + + Unless there's an error, it always returns the amount of data it could + produce, even if that's too big for the buffer, but it won't copy more + than requested to userspace. If the buffer pointer is NULL then no copy + will take place. + + A NUL character is included at the end of the string if the buffer is + sufficiently big. This is included in the returned count. If no LSM is + in force then an empty string will be returned. + + A process must have view permission on the key for this function to be + successful. + + =============== KERNEL SERVICES ===============
include/linux/keyctl.h +1 -0
@@ -49,5 +49,6 @@#define KEYCTL_SET_REQKEY_KEYRING 14/* set default request-key keyring */ #define KEYCTL_SET_TIMEOUT 15/* set key timeout */ #define KEYCTL_ASSUME_AUTHORITY 16/* assume request_key() authorisation */ +#define KEYCTL_GET_SECURITY 17/* get key security label */ #endif /* _LINUX_KEYCTL_H */
include/linux/security.h +19 -1
@@ -959,6 +959,17 @@ struct request_sock;* @perm describes the combination of permissions required of this key. * Return 1 if permission granted, 0 if permission denied and -ve it the * normal permissions model should be effected. +* @key_getsecurity: +* Get a textual representation of the security context attached to a key +* for the purposes of honouring KEYCTL_GETSECURITY. This function +* allocates the storage for the NUL-terminated string and the caller +* should free it. +* @key points to the key to be queried. +* @_buffer points to a pointer that should be set to point to the +* resulting string (if no label or an error occurs). +* Return the length of the string (including terminating NUL) or -ve if +* an error. +* May also return 0 (and a NULL buffer pointer) if there is no label. * * Security hooks affecting all System V IPC operations. *
@@ -1437,7 +1448,7 @@ struct security_operations {int (*key_permission)(key_ref_t key_ref,struct task_struct *context,key_perm_t perm); - +int (*key_getsecurity)(struct key *key,char **_buffer);#endif /* CONFIG_KEYS */ };
@@ -2567,6 +2578,7 @@ int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long fvoid security_key_free (struct key *key);int security_key_permission (key_ref_t key_ref,struct task_struct *context,key_perm_t perm); +int security_key_getsecurity (struct key *key,char **_buffer);#else
@@ -2588,6 +2600,12 @@ static inline int security_key_permission(key_ref_t key_ref,return 0 ; } +static inline int security_key_getsecurity (struct key *key,char **_buffer) +{ + *_buffer =NULL ; +return 0 ; +} +#endif #endif /* CONFIG_KEYS */
security/dummy.c +8 -0
@@ -949,6 +949,13 @@ static inline int dummy_key_permission(key_ref_t key_ref, {return 0 ; } + +static int dummy_key_getsecurity (struct key *key,char **_buffer) +{ + *_buffer =NULL ; +return 0 ; +} +#endif /* CONFIG_KEYS */ struct security_operations dummy_security_ops;
@@ -1133,6 +1140,7 @@ void security_fixup_ops (struct security_operations *ops)set_to_dummy_if_null (ops, key_alloc);set_to_dummy_if_null (ops, key_free);set_to_dummy_if_null (ops, key_permission); +set_to_dummy_if_null (ops, key_getsecurity);#endif /* CONFIG_KEYS */ }
security/keys/compat.c +3 -0
@@ -79,6 +79,9 @@ asmlinkage long compat_sys_keyctl(u32 option,case KEYCTL_ASSUME_AUTHORITY :return keyctl_assume_authority (arg2); +case KEYCTL_GET_SECURITY : +return keyctl_get_security (arg2,compat_ptr (arg3), arg4); +default :return -EOPNOTSUPP ; }
security/keys/keyctl.c +66 -0
84 lines not on this page · raw message
security/security.c +5 -0
@@ -1079,4 +1079,9 @@ int security_key_permission(key_ref_t key_ref, return security_ops->key_permission(key_ref, context, perm); } +int security_key_getsecurity (struct key *key,char **_buffer) +{ +return security_ops->key_getsecurity (key, _buffer); +} +#endif /* CONFIG_KEYS */
security/selinux/hooks.c +18 -3
@@ -4768,6 +4768,20 @@ static int selinux_key_permission(key_ref_t key_ref, SECCLASS_KEY, perm, NULL); } +static int selinux_key_getsecurity (struct key *key,char **_buffer) +{ +struct key_security_struct *ksec = key->security; +char *context =NULL ; +unsigned len; +int rc; + + rc =security_sid_to_context (ksec->sid, &context, &len); +if (!rc) + rc = len; + *_buffer = context; +return rc; +} +#endif static struct security_operations selinux_ops = {
@@ -4943,9 +4957,10 @@ static struct security_operations selinux_ops = {#endif #ifdef CONFIG_KEYS - .key_alloc = selinux_key_alloc, - .key_free = selinux_key_free, - .key_permission = selinux_key_permission, + .key_alloc = selinux_key_alloc, + .key_free = selinux_key_free, + .key_permission = selinux_key_permission, + .key_getsecurity = selinux_key_getsecurity,#endif };
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Re: [PATCH 04/26] KEYS: Add keyctl function to get a security label
Quoted 17 lines · David Howells
Add a
keyctl()function to get the security label of a key.The following is added to
Documentation/keys.txt:(*) Get the LSM security context attached to a key.
long keyctl(KEYCTL_GET_SECURITY,
key_serial_tkey, char *buffer,
size_tbuflen)This function returns a string that represents the LSM security context attached to a key in the buffer provided.
Unless there's an error, it always returns the amount of data it could produce, even if that's too big for the buffer, but it won't copy more than requested to userspace. If the buffer pointer is NULL then no copy will take place.
Quoted 8 lines
A NUL character is included at the end of the string if the buffer is sufficiently big. This is included in the returned count. If no LSM is in force then an empty string will be returned.
A process must have view permission on the key for this function to be successful.
Signed-off-by David Howells <[email protected]>
You can push that one up anytime.
Quoted 292 lines
---
Documentation/keys.txt | 21 +++++++++++++++ include/linux/keyctl.h | 1 + include/linux/security.h | 20 +++++++++++++- security/dummy.c | 8 ++++++ security/keys/compat.c | 3 ++ security/keys/keyctl.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++ security/security.c | 5 +++ security/selinux/hooks.c | 21 +++++++++++++-- 8 files changed, 141 insertions(+), 4 deletions(-)Documentation/keys.txt +21
-0@@ -711,6 +711,27 @@ The keyctl syscall functions are: The assumed authoritative key is inherited across fork and exec. + (*) Get the LSM security context attached to a key. + + long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer, + size_t buflen) + + This function returns a string that represents the LSM security context + attached to a key in the buffer provided. + + Unless there's an error, it always returns the amount of data it could + produce, even if that's too big for the buffer, but it won't copy more + than requested to userspace. If the buffer pointer is NULL then no copy + will take place. + + A NUL character is included at the end of the string if the buffer is + sufficiently big. This is included in the returned count. If no LSM is + in force then an empty string will be returned. + + A process must have view permission on the key for this function to be + successful. + + =============== KERNEL SERVICES ===============include/linux/keyctl.h +1
-0@@ -49,5 +49,6 @@#define KEYCTL_SET_REQKEY_KEYRING 14/* set default request-key keyring */ #define KEYCTL_SET_TIMEOUT 15/* set key timeout */ #define KEYCTL_ASSUME_AUTHORITY 16/* assume request_key() authorisation */ +#define KEYCTL_GET_SECURITY 17/* get key security label */ #endif /* _LINUX_KEYCTL_H */ include/linux/security.h +19
-1@@ -959,6 +959,17 @@ struct request_sock;* @perm describes the combination of permissions required of this key. * Return 1 if permission granted, 0 if permission denied and -ve it the * normal permissions model should be effected. +* @key_getsecurity: +* Get a textual representation of the security context attached to a key +* for the purposes of honouring KEYCTL_GETSECURITY. This function +* allocates the storage for the NUL-terminated string and the caller +* should free it. +* @key points to the key to be queried. +* @_buffer points to a pointer that should be set to point to the +* resulting string (if no label or an error occurs). +* Return the length of the string (including terminating NUL) or -ve if +* an error. +* May also return 0 (and a NULL buffer pointer) if there is no label. * * Security hooks affecting all System V IPC operations. * @@ -1437,7 +1448,7 @@ struct security_operations {int (*key_permission)(key_ref_t key_ref,struct task_struct *context,key_perm_t perm); - +int (*key_getsecurity)(struct key *key,char **_buffer);#endif /* CONFIG_KEYS */ };@@ -2567,6 +2578,7 @@ int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long fvoid security_key_free (struct key *key);int security_key_permission (key_ref_t key_ref,struct task_struct *context,key_perm_t perm); +int security_key_getsecurity (struct key *key,char **_buffer);#else @@ -2588,6 +2600,12 @@ static inline int security_key_permission(key_ref_t key_ref,return 0 ; } +static inline int security_key_getsecurity (struct key *key,char **_buffer) +{ + *_buffer =NULL ; +return 0 ; +} +#endif #endif /* CONFIG_KEYS */ security/dummy.c +8
-0@@ -949,6 +949,13 @@ static inline int dummy_key_permission(key_ref_t key_ref, {return 0 ; } + +static int dummy_key_getsecurity (struct key *key,char **_buffer) +{ + *_buffer =NULL ; +return 0 ; +} +#endif /* CONFIG_KEYS */ struct security_operations dummy_security_ops;@@ -1133,6 +1140,7 @@ void security_fixup_ops (struct security_operations *ops)set_to_dummy_if_null (ops, key_alloc);set_to_dummy_if_null (ops, key_free);set_to_dummy_if_null (ops, key_permission); +set_to_dummy_if_null (ops, key_getsecurity);#endif /* CONFIG_KEYS */ }security/keys/compat.c +3
-0@@ -79,6 +79,9 @@ asmlinkage long compat_sys_keyctl(u32 option,case KEYCTL_ASSUME_AUTHORITY :return keyctl_assume_authority (arg2); +case KEYCTL_GET_SECURITY : +return keyctl_get_security (arg2,compat_ptr (arg3), arg4); +default :return -EOPNOTSUPP ; }security/keys/keyctl.c +66
-0@@ -20,6 +20,7 @@#include <linux/string.h> #include <linux/err.h> #include <linux/vmalloc.h> +#include <linux/security.h> #include <asm/uaccess.h> #include "internal.h" @@ -1080,6 +1081,66 @@ error: }/* end keyctl_assume_authority() */ +/* +* get the security label of a key +* - the key must grant us view permission +* - if there's a buffer, we place up to buflen bytes of data into it +* - unless there's an error, we return the amount of information available, +* irrespective of how much we may have copied (including the terminal NUL) +* - implements keyctl(KEYCTL_GET_SECURITY) +*/ +long keyctl_get_security (key_serial_t keyid, +char __user *buffer, +size_t buflen) +{ +struct key *key, *instkey; +key_ref_t key_ref; +char *context; +long ret; + + key_ref =lookup_user_key (NULL , keyid,0 ,1 ,KEY_VIEW ); +if (IS_ERR (key_ref)) { +if (PTR_ERR (key_ref) != -EACCES ) +return PTR_ERR (key_ref); + +/* viewing a key under construction is also permitted if we +* have the authorisation token handy */ + instkey =key_get_instantiation_authkey (keyid); +if (IS_ERR (instkey)) +return PTR_ERR (key_ref); +key_put (instkey); + + key_ref =lookup_user_key (NULL , keyid,0 ,1 ,0 ); +if (IS_ERR (key_ref)) +return PTR_ERR (key_ref); + } + + key =key_ref_to_ptr (key_ref); + ret =security_key_getsecurity (key, &context); +if (ret ==0 ) { +/* if no information was returned, give userspace an empty +* string */ + ret =1 ; +if (buffer && buflen >0 && +copy_to_user (buffer,"" ,1 ) !=0 ) + ret = -EFAULT ; + }else if (ret >0 ) { +/* return as much data as there's room for */ +if (buffer && buflen >0 ) { +if (buflen > ret) + buflen = ret; + +if (copy_to_user (buffer, context, buflen) !=0 ) + ret = -EFAULT ; + } + +kfree (context); + } + +key_ref_put (key_ref); +return ret; +} +/*****************************************************************************/ /* * the key control system call @@ -1160,6 +1221,11 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,case KEYCTL_ASSUME_AUTHORITY :return keyctl_assume_authority ((key_serial_t ) arg2); +case KEYCTL_GET_SECURITY : +return keyctl_get_security ((key_serial_t ) arg2, + (char *) arg3, + (size_t ) arg4); +default :return -EOPNOTSUPP ; }security/security.c +5
-0@@ -1079,4 +1079,9 @@ int security_key_permission(key_ref_t key_ref, return security_ops->key_permission(key_ref, context, perm); } +int security_key_getsecurity (struct key *key,char **_buffer) +{ +return security_ops->key_getsecurity (key, _buffer); +} +#endif /* CONFIG_KEYS */ security/selinux/hooks.c +18
-3@@ -4768,6 +4768,20 @@ static int selinux_key_permission(key_ref_t key_ref, SECCLASS_KEY, perm, NULL); } +static int selinux_key_getsecurity (struct key *key,char **_buffer) +{ +struct key_security_struct *ksec = key->security; +char *context =NULL ; +unsigned len; +int rc; + + rc =security_sid_to_context (ksec->sid, &context, &len); +if (!rc) + rc = len; + *_buffer = context; +return rc; +} +#endif static struct security_operations selinux_ops = {@@ -4943,9 +4957,10 @@ static struct security_operations selinux_ops = {#endif #ifdef CONFIG_KEYS - .key_alloc = selinux_key_alloc, - .key_free = selinux_key_free, - .key_permission = selinux_key_permission, + .key_alloc = selinux_key_alloc, + .key_free = selinux_key_free, + .key_permission = selinux_key_permission, + .key_getsecurity = selinux_key_getsecurity,#endif };
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 5/26 Security: Change current->fs[ug]id to current_fs[ug]id()
In reply to David HowellsChange current->fs[ug]id to current_fs[ug]id() so that fsgid and fsuid can be separated from the task_struct.
---
arch/ia64/kernel/perfmon.c | 4 ++-- arch/powerpc/platforms/cell/spufs/inode.c | 4 ++-- drivers/isdn/capi/capifs.c | 4 ++-- drivers/usb/core/inode.c | 4 ++-- fs/9p/fid.c | 2 +- fs/9p/vfs_inode.c | 4 ++-- fs/9p/vfs_super.c | 4 ++-- fs/affs/inode.c | 4 ++-- fs/anon_inodes.c | 4 ++-- fs/attr.c | 4 ++-- fs/bfs/dir.c | 4 ++-- fs/cifs/cifsproto.h | 2 +- fs/cifs/dir.c | 12 ++++++------ fs/cifs/inode.c | 8 ++++---- fs/cifs/misc.c | 4 ++-- fs/coda/cache.c | 6 +++--- fs/coda/upcall.c | 4 ++-- fs/devpts/inode.c | 4 ++-- fs/dquot.c | 2 +- fs/exec.c | 4 ++-- fs/ext2/balloc.c | 2 +- fs/ext2/ialloc.c | 4 ++-- fs/ext2/ioctl.c | 2 +- fs/ext3/balloc.c | 2 +- fs/ext3/ialloc.c | 4 ++-- fs/ext4/balloc.c | 2 +- fs/ext4/ialloc.c | 4 ++-- fs/fuse/dev.c | 4 ++-- fs/gfs2/inode.c | 10 +++++----- fs/hfs/inode.c | 4 ++-- fs/hfsplus/inode.c | 4 ++-- fs/hpfs/namei.c | 24 ++++++++++++------------ fs/hugetlbfs/inode.c | 16 ++++++++-------- fs/jffs2/fs.c | 4 ++-- fs/jfs/jfs_inode.c | 4 ++-- fs/locks.c | 2 +- fs/minix/bitmap.c | 4 ++-- fs/namei.c | 8 ++++---- fs/nfsd/vfs.c | 4 ++-- fs/ocfs2/dlm/dlmfs.c | 8 ++++---- fs/ocfs2/namei.c | 4 ++-- fs/pipe.c | 4 ++-- fs/posix_acl.c | 4 ++-- fs/ramfs/inode.c | 4 ++-- fs/reiserfs/namei.c | 4 ++-- fs/sysv/ialloc.c | 4 ++-- fs/udf/ialloc.c | 4 ++-- fs/udf/namei.c | 2 +- fs/ufs/ialloc.c | 4 ++-- fs/xfs/linux-2.6/xfs_linux.h | 4 ++-- fs/xfs/xfs_acl.c | 6 +++--- fs/xfs/xfs_attr.c | 2 +- fs/xfs/xfs_inode.c | 6 +++--- fs/xfs/xfs_vnodeops.c | 8 ++++---- include/linux/fs.h | 2 +- include/linux/sched.h | 3 +++ ipc/mqueue.c | 4 ++-- kernel/cgroup.c | 4 ++-- mm/shmem.c | 8 ++++---- net/9p/client.c | 2 +- net/socket.c | 4 ++-- net/sunrpc/auth.c | 8 ++++---- security/commoncap.c | 8 ++++---- security/keys/key.c | 2 +- security/keys/keyctl.c | 2 +- security/keys/request_key.c | 10 +++++----- security/keys/request_key_auth.c | 2 +- 67 files changed, 163 insertions(+), 160 deletions(-)
arch/ia64/kernel/perfmon.c +2 -2
@@ -2206,8 +2206,8 @@ pfm_alloc_fd(struct file **cfile)DPRINT (("new inode ino=%ld @%p\n" , inode->i_ino, inode)); inode->i_mode =S_IFCHR |S_IRUGO ; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid ();sprintf (name,"[%lu]" , inode->i_ino); this.name = name;
arch/powerpc/platforms/cell/spufs/inode.c +2 -2
@@ -85,8 +85,8 @@ spufs_new_inode(struct super_block *sb, int mode) goto out; inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_blocks =0 ; inode->i_atime = inode->i_mtime = inode->i_ctime =CURRENT_TIME ; out:
drivers/isdn/capi/capifs.c +2 -2
@@ -148,8 +148,8 @@ void capifs_new_ncci(unsigned int number, dev_t device)if (!inode)return ; inode->i_ino = number+2 ; - inode->i_uid = config.setuid ? config.uid : current->fsuid; - inode->i_gid = config.setgid ? config.gid : current->fsgid; + inode->i_uid = config.setuid ? config.uid :current_fsuid (); + inode->i_gid = config.setgid ? config.gid :current_fsgid (); inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME ;init_special_inode (inode,S_IFCHR |config.mode, device);//inode->i_op = &capifs_file_inode_operations;
drivers/usb/core/inode.c +2 -2
@@ -246,8 +246,8 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t deif (inode) { inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_blocks =0 ; inode->i_atime = inode->i_mtime = inode->i_ctime =CURRENT_TIME ;switch (mode &S_IFMT ) {
fs/9p/fid.c +1 -1
@@ -121,7 +121,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)switch (access) {case V9FS_ACCESS_SINGLE :case V9FS_ACCESS_USER : - uid = current->fsuid; + uid =current_fsuid (); any =0 ;break ;
fs/9p/vfs_inode.c +2 -2
@@ -202,8 +202,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) inode =new_inode (sb);if (inode) { inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_blocks =0 ; inode->i_rdev =0 ; inode->i_atime = inode->i_mtime = inode->i_ctime =CURRENT_TIME ;
fs/9p/vfs_super.c +2 -2
@@ -112,8 +112,8 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,struct v9fs_session_info *v9ses =NULL ;struct p9_stat *st =NULL ;int mode =S_IRWXUGO |S_ISVTX ; -uid_t uid = current->fsuid; -gid_t gid = current->fsgid; +uid_t uid =current_fsuid (); +gid_t gid =current_fsgid ();struct p9_fid *fid;int retval =0 ;
fs/affs/inode.c +2 -2
@@ -305,8 +305,8 @@ affs_new_inode(struct inode *dir)mark_buffer_dirty_inode (bh, inode);affs_brelse (bh); - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_ino = block; inode->i_nlink =1 ; inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ;
fs/anon_inodes.c +2 -2
@@ -162,8 +162,8 @@ static struct inode *anon_inode_mkinode(void)*/ inode->i_state =I_DIRTY ; inode->i_mode =S_IRUSR |S_IWUSR ; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_atime = inode->i_mtime = inode->i_ctime =CURRENT_TIME ;return inode; }
fs/attr.c +2 -2
@@ -29,13 +29,13 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)/* Make sure a caller can chown. */ if ((ia_valid &ATTR_UID ) && - (current->fsuid != inode->i_uid || + (current_fsuid () != inode->i_uid || attr->ia_uid != inode->i_uid) && !capable (CAP_CHOWN )) goto error;/* Make sure caller can chgrp. */ if ((ia_valid &ATTR_GID ) && - (current->fsuid != inode->i_uid || + (current_fsuid () != inode->i_uid || (!in_group_p (attr->ia_gid) && attr->ia_gid != inode->i_gid)) && !capable (CAP_CHOWN )) goto error;
fs/bfs/dir.c +2 -2
@@ -104,8 +104,8 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, int mode, }set_bit (ino, info->si_imap); info->si_freei--; - inode->i_uid = current->fsuid; - inode->i_gid = (dir->i_mode &S_ISGID ) ? dir->i_gid : current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid = (dir->i_mode &S_ISGID ) ? dir->i_gid :current_fsgid (); inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ; inode->i_blocks =0 ; inode->i_op = &bfs_file_inops;
fs/cifs/cifsproto.h +1 -1
@@ -39,7 +39,7 @@ extern int smb_send(struct socket *, struct smb_hdr *, unsigned int /* length */ , struct sockaddr *);extern unsigned int _GetXid (void );extern void _FreeXid (unsigned int ); -#define GetXid () (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid)); +#define GetXid () (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current_fsuid()));#define FreeXid (curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}extern char *build_path_from_dentry (struct dentry *);extern char *build_wildcard_path_from_dentry (struct dentry *direntry);
fs/cifs/dir.c +6 -6
@@ -211,8 +211,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, mode &= ~current->fs->umask;if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, - (__u64)current->fsuid, - (__u64)current->fsgid, + (__u64)current_fsuid(), + (__u64)current_fsgid(), 0 /* dev */, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -246,8 +246,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,if ((oplock &CIFS_CREATE_ACTION ) && (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID )) { - newinode->i_uid = current->fsuid; - newinode->i_gid = current->fsgid; + newinode->i_uid =current_fsuid (); + newinode->i_gid =current_fsgid (); } } }
@@ -340,8 +340,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, mode &= ~current->fs->umask;if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { rc =CIFSSMBUnixSetPerms (xid, pTcon, full_path, - mode, (__u64 )current->fsuid, - (__u64 )current->fsgid, + mode, (__u64 )current_fsuid (), + (__u64 )current_fsgid (), device_number, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &CIFS_MOUNT_MAP_SPECIAL_CHR );
fs/cifs/inode.c +4 -4
@@ -1031,8 +1031,8 @@ mkdir_get_info:if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, - (__u64)current->fsuid, - (__u64)current->fsgid, + (__u64)current_fsuid(), + (__u64)current_fsgid(), 0 /* dev_t */, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -1055,9 +1055,9 @@ mkdir_get_info:if (cifs_sb->mnt_cifs_flags &CIFS_MOUNT_SET_UID ) { direntry->d_inode->i_uid = - current->fsuid; +current_fsuid (); direntry->d_inode->i_gid = - current->fsgid; +current_fsgid (); } } }
fs/cifs/misc.c +2 -2
@@ -351,13 +351,13 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,/* BB Add support for establishing new tCon and SMB Session */ /* with userid/password pairs found on the smb session */ /* for other target tcp/ip addresses BB */ -if (current->fsuid != treeCon->ses->linux_uid) { +if (current_fsuid () != treeCon->ses->linux_uid) {cFYI (1 , ("Multiuser mode and UID " "did not match tcon uid" ));read_lock (&GlobalSMBSeslock);list_for_each (temp_item, &GlobalSMBSessionList) { ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList); -if (ses->linux_uid == current->fsuid) { +if (ses->linux_uid ==current_fsuid ()) {if (ses->server == treeCon->ses->server) {cFYI (1 , ("found matching uid substitute right smb_uid" )); buffer->Uid = ses->Suid;
fs/coda/cache.c +3 -3
@@ -32,8 +32,8 @@ void coda_cache_enter(struct inode *inode, int mask)struct coda_inode_info *cii =ITOC (inode); cii->c_cached_epoch =atomic_read (&permission_epoch); -if (cii->c_uid != current->fsuid) { - cii->c_uid = current->fsuid; +if (cii->c_uid !=current_fsuid ()) { + cii->c_uid =current_fsuid (); cii->c_cached_perm = mask; }else cii->c_cached_perm |= mask;
@@ -60,7 +60,7 @@ int coda_cache_check(struct inode *inode, int mask)int hit; hit = (mask & cii->c_cached_perm) == mask && - cii->c_uid == current->fsuid && + cii->c_uid ==current_fsuid () && cii->c_cached_epoch ==atomic_read (&permission_epoch);return hit;
fs/coda/upcall.c +2 -2
@@ -54,9 +54,9 @@ static void *alloc_upcall(int opcode, int size) inp->ih.pgid =task_pgrp_nr (current);#ifdef CONFIG_CODA_FS_OLD_API memset (&inp->ih.cred,0 ,sizeof (struct coda_cred )); - inp->ih.cred.cr_fsuid = current->fsuid; + inp->ih.cred.cr_fsuid =current_fsuid ();#else - inp->ih.uid = current->fsuid; + inp->ih.uid =current_fsuid ();#endif return (void *)inp; }
fs/devpts/inode.c +2 -2
@@ -172,8 +172,8 @@ int devpts_pty_new(struct tty_struct *tty)return -ENOMEM ; inode->i_ino = number+2 ; - inode->i_uid = config.setuid ? config.uid : current->fsuid; - inode->i_gid = config.setgid ? config.gid : current->fsgid; + inode->i_uid = config.setuid ? config.uid :current_fsuid (); + inode->i_gid = config.setgid ? config.gid :current_fsgid (); inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME ;init_special_inode (inode,S_IFCHR |config.mode, device); inode->i_private = tty;
fs/dquot.c +1 -1
@@ -849,7 +849,7 @@ static inline int need_print_warning(struct dquot *dquot)switch (dquot->dq_type) {case USRQUOTA : -return current->fsuid == dquot->dq_id; +return current_fsuid () == dquot->dq_id;case GRPQUOTA :return in_group_p (dquot->dq_id); }
fs/exec.c +2 -2
@@ -1678,7 +1678,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)struct inode * inode;struct file * file;int retval =0 ; -int fsuid = current->fsuid; +int fsuid =current_fsuid ();int flag =0 ;int ispipe =0 ;unsigned long core_limit = current->signal->rlim[RLIMIT_CORE ].rlim_cur;
@@ -1784,7 +1784,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)* Dont allow local users get cute and trick others to coredump * into their pre-created files: */ -if (inode->i_uid != current->fsuid) +if (inode->i_uid !=current_fsuid ()) goto close_fail;if (!file->f_op) goto close_fail;
fs/ext2/balloc.c +1 -1
@@ -1128,7 +1128,7 @@ static int ext2_has_free_blocks(struct ext2_sb_info *sbi) free_blocks =percpu_counter_read_positive (&sbi->s_freeblocks_counter); root_blocks =le32_to_cpu (sbi->s_es->s_r_blocks_count);if (free_blocks < root_blocks +1 && !capable (CAP_SYS_RESOURCE ) && - sbi->s_resuid != current->fsuid && + sbi->s_resuid !=current_fsuid () && (sbi->s_resgid ==0 || !in_group_p (sbi->s_resgid))) {return 0 ; }
fs/ext2/ialloc.c +2 -2
@@ -554,7 +554,7 @@ got: sb->s_dirt =1 ;mark_buffer_dirty (bh2); - inode->i_uid = current->fsuid; + inode->i_uid =current_fsuid ();if (test_opt (sb,GRPID )) inode->i_gid = dir->i_gid;else if (dir->i_mode &S_ISGID ) {
@@ -562,7 +562,7 @@ got:if (S_ISDIR (mode)) mode |=S_ISGID ; }else - inode->i_gid = current->fsgid; + inode->i_gid =current_fsgid (); inode->i_mode = mode; inode->i_ino = ino;
fs/ext2/ioctl.c +1 -1
@@ -105,7 +105,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,if (IS_RDONLY (inode))return -EROFS ; -if ((current->fsuid != inode->i_uid) && !capable (CAP_FOWNER )) +if ((current_fsuid () != inode->i_uid) && !capable (CAP_FOWNER ))return -EACCES ;if (get_user (rsv_window_size, (int __user *)arg))
fs/ext3/balloc.c +1 -1
@@ -1360,7 +1360,7 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi) free_blocks =percpu_counter_read_positive (&sbi->s_freeblocks_counter); root_blocks =le32_to_cpu (sbi->s_es->s_r_blocks_count);if (free_blocks < root_blocks +1 && !capable (CAP_SYS_RESOURCE ) && - sbi->s_resuid != current->fsuid && + sbi->s_resuid !=current_fsuid () && (sbi->s_resgid ==0 || !in_group_p (sbi->s_resgid))) {return 0 ; }
fs/ext3/ialloc.c +2 -2
@@ -543,7 +543,7 @@ got:percpu_counter_inc (&sbi->s_dirs_counter); sb->s_dirt =1 ; - inode->i_uid = current->fsuid; + inode->i_uid =current_fsuid ();if (test_opt (sb,GRPID )) inode->i_gid = dir->i_gid;else if (dir->i_mode &S_ISGID ) {
@@ -551,7 +551,7 @@ got:if (S_ISDIR (mode)) mode |=S_ISGID ; }else - inode->i_gid = current->fsgid; + inode->i_gid =current_fsgid (); inode->i_mode = mode; inode->i_ino = ino;
fs/ext4/balloc.c +1 -1
@@ -1480,7 +1480,7 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi) free_blocks =percpu_counter_read_positive (&sbi->s_freeblocks_counter); root_blocks =ext4_r_blocks_count (sbi->s_es);if (free_blocks < root_blocks +1 && !capable (CAP_SYS_RESOURCE ) && - sbi->s_resuid != current->fsuid && + sbi->s_resuid !=current_fsuid () && (sbi->s_resgid ==0 || !in_group_p (sbi->s_resgid))) {return 0 ; }
fs/ext4/ialloc.c +2 -2
@@ -674,7 +674,7 @@ got:percpu_counter_inc (&sbi->s_dirs_counter); sb->s_dirt =1 ; - inode->i_uid = current->fsuid; + inode->i_uid =current_fsuid ();if (test_opt (sb,GRPID )) inode->i_gid = dir->i_gid;else if (dir->i_mode &S_ISGID ) {
@@ -682,7 +682,7 @@ got:if (S_ISDIR (mode)) mode |=S_ISGID ; }else - inode->i_gid = current->fsgid; + inode->i_gid =current_fsgid (); inode->i_mode = mode; inode->i_ino = ino + group *EXT4_INODES_PER_GROUP (sb);
fs/fuse/dev.c +2 -2
@@ -79,8 +79,8 @@ static void __fuse_put_request(struct fuse_req *req)static void fuse_req_init_context (struct fuse_req *req) { - req->in.h.uid = current->fsuid; - req->in.h.gid = current->fsgid; + req->in.h.uid =current_fsuid (); + req->in.h.gid =current_fsgid (); req->in.h.pid = current->pid; }
fs/gfs2/inode.c +5 -5
@@ -688,18 +688,18 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode, (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {if (S_ISDIR (*mode)) *mode |=S_ISUID ; -else if (dip->i_inode.i_uid != current->fsuid) +else if (dip->i_inode.i_uid !=current_fsuid ()) *mode &= ~07111 ; *uid = dip->i_inode.i_uid; } else - *uid = current->fsuid; + *uid =current_fsuid ();if (dip->i_inode.i_mode &S_ISGID ) {if (S_ISDIR (*mode)) *mode |=S_ISGID ; *gid = dip->i_inode.i_gid; }else - *gid = current->fsgid; + *gid =current_fsgid (); }static int alloc_dinode (struct gfs2_inode *dip,u64 *no_addr,u64 *generation)
@@ -1108,8 +1108,8 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,return -EPERM ;if ((dip->i_inode.i_mode &S_ISVTX ) && - dip->i_inode.i_uid != current->fsuid && - ip->i_inode.i_uid != current->fsuid && !capable (CAP_FOWNER )) + dip->i_inode.i_uid !=current_fsuid () && + ip->i_inode.i_uid !=current_fsuid () && !capable (CAP_FOWNER ))return -EPERM ;if (IS_APPEND (&dip->i_inode))
fs/hfs/inode.c +2 -2
@@ -155,8 +155,8 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)hfs_cat_build_key (sb, (btree_key *)&HFS_I (inode)->cat_key, dir->i_ino, name); inode->i_ino =HFS_SB (sb)->next_id++; inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_nlink =1 ; inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ;HFS_I (inode)->flags =0 ;
fs/hfsplus/inode.c +2 -2
@@ -312,8 +312,8 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode) inode->i_ino =HFSPLUS_SB (sb).next_cnid++; inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_nlink =1 ; inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ;INIT_LIST_HEAD (&HFSPLUS_I (inode).open_dir_list);
fs/hpfs/namei.c +12 -12
@@ -92,11 +92,11 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)inc_nlink (dir);insert_inode_hash (result); -if (result->i_uid != current->fsuid || - result->i_gid != current->fsgid || +if (result->i_uid !=current_fsuid () || + result->i_gid !=current_fsgid () || result->i_mode != (mode |S_IFDIR )) { - result->i_uid = current->fsuid; - result->i_gid = current->fsgid; + result->i_uid =current_fsuid (); + result->i_gid =current_fsgid (); result->i_mode = mode |S_IFDIR ;hpfs_write_inode_nolock (result); }
@@ -184,11 +184,11 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, strucinsert_inode_hash (result); -if (result->i_uid != current->fsuid || - result->i_gid != current->fsgid || +if (result->i_uid !=current_fsuid () || + result->i_gid !=current_fsgid () || result->i_mode != (mode |S_IFREG )) { - result->i_uid = current->fsuid; - result->i_gid = current->fsgid; + result->i_uid =current_fsuid (); + result->i_gid =current_fsgid (); result->i_mode = mode |S_IFREG ;hpfs_write_inode_nolock (result); }
@@ -247,8 +247,8 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t result->i_mtime.tv_nsec =0 ; result->i_atime.tv_nsec =0 ;hpfs_i (result)->i_ea_size =0 ; - result->i_uid = current->fsuid; - result->i_gid = current->fsgid; + result->i_uid =current_fsuid (); + result->i_gid =current_fsgid (); result->i_nlink =1 ; result->i_size =0 ; result->i_blocks =1 ;
@@ -325,8 +325,8 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy result->i_atime.tv_nsec =0 ;hpfs_i (result)->i_ea_size =0 ; result->i_mode =S_IFLNK |0777 ; - result->i_uid = current->fsuid; - result->i_gid = current->fsgid; + result->i_uid =current_fsuid (); + result->i_gid =current_fsgid (); result->i_blocks =1 ; result->i_nlink =1 ; result->i_size =strlen (symlink);
fs/hugetlbfs/inode.c +8 -8
@@ -543,9 +543,9 @@ static int hugetlbfs_mknod(struct inode *dir,if (S_ISDIR (mode)) mode |=S_ISGID ; }else { - gid = current->fsgid; + gid =current_fsgid (); } - inode =hugetlbfs_get_inode (dir->i_sb, current->fsuid, gid, mode, dev); + inode =hugetlbfs_get_inode (dir->i_sb,current_fsuid (), gid, mode, dev);if (inode) { dir->i_ctime = dir->i_mtime =CURRENT_TIME ;d_instantiate (dentry, inode);
@@ -578,9 +578,9 @@ static int hugetlbfs_symlink(struct inode *dir,if (dir->i_mode &S_ISGID ) gid = dir->i_gid;else - gid = current->fsgid; + gid =current_fsgid (); - inode =hugetlbfs_get_inode (dir->i_sb, current->fsuid, + inode =hugetlbfs_get_inode (dir->i_sb,current_fsuid (), gid,S_IFLNK |S_IRWXUGO ,0 );if (inode) {int l =strlen (symname)+1 ;
@@ -819,8 +819,8 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) config.nr_blocks =-1 ;/* No limit on size by default */ config.nr_inodes =-1 ;/* No limit on number of inodes by default */ - config.uid = current->fsuid; - config.gid = current->fsgid; + config.uid =current_fsuid (); + config.gid =current_fsgid (); config.mode =0755 ; ret =hugetlbfs_parse_options (data, &config);if (ret)
@@ -933,8 +933,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size) goto out_shm_unlock; error = -ENOSPC ; - inode =hugetlbfs_get_inode (root->d_sb, current->fsuid, - current->fsgid,S_IFREG |S_IRWXUGO ,0 ); + inode =hugetlbfs_get_inode (root->d_sb,current_fsuid (), +current_fsgid (),S_IFREG |S_IRWXUGO ,0 );if (!inode) goto out_dentry;
fs/jffs2/fs.c +2 -2
@@ -425,14 +425,14 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_imemset (ri,0 ,sizeof (*ri));/* Set OS-specific defaults for new inodes */ - ri->uid =cpu_to_je16 (current->fsuid); + ri->uid =cpu_to_je16 (current_fsuid ());if (dir_i->i_mode &S_ISGID ) { ri->gid =cpu_to_je16 (dir_i->i_gid);if (S_ISDIR (mode)) mode |=S_ISGID ; }else { - ri->gid =cpu_to_je16 (current->fsgid); + ri->gid =cpu_to_je16 (current_fsgid ()); }/* POSIX ACLs have to be processed now, at least partly.
fs/jfs/jfs_inode.c +2 -2
@@ -93,13 +93,13 @@ struct inode *ialloc(struct inode *parent, umode_t mode)return ERR_PTR (rc); } - inode->i_uid = current->fsuid; + inode->i_uid =current_fsuid ();if (parent->i_mode &S_ISGID ) { inode->i_gid = parent->i_gid;if (S_ISDIR (mode)) mode |=S_ISGID ; }else - inode->i_gid = current->fsgid; + inode->i_gid =current_fsgid ();/* * New inodes need to save sane values on disk when
fs/locks.c +1 -1
@@ -1358,7 +1358,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)struct inode *inode = dentry->d_inode;int error, rdlease_count =0 , wrlease_count =0 ; -if ((current->fsuid != inode->i_uid) && !capable (CAP_LEASE )) +if ((current_fsuid () != inode->i_uid) && !capable (CAP_LEASE ))return -EACCES ;if (!S_ISREG (inode->i_mode))return -EINVAL ;
fs/minix/bitmap.c +2 -2
@@ -262,8 +262,8 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)iput (inode);return NULL ; } - inode->i_uid = current->fsuid; - inode->i_gid = (dir->i_mode &S_ISGID ) ? dir->i_gid : current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid = (dir->i_mode &S_ISGID ) ? dir->i_gid :current_fsgid (); inode->i_ino = j; inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ; inode->i_blocks =0 ;
fs/namei.c +4 -4
@@ -184,7 +184,7 @@ int generic_permission(struct inode *inode, int mask, {umode_t mode = inode->i_mode; -if (current->fsuid == inode->i_uid) +if (current_fsuid () == inode->i_uid) mode >>=6 ;else {if (IS_POSIXACL (inode) && (mode &S_IRWXG ) && check_acl) {
@@ -452,7 +452,7 @@ static int exec_permission_lite(struct inode *inode,if (inode->i_op && inode->i_op->permission)return -EAGAIN ; -if (current->fsuid == inode->i_uid) +if (current_fsuid () == inode->i_uid) mode >>=6 ;else if (in_group_p (inode->i_gid)) mode >>=3 ;
@@ -1435,9 +1435,9 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) {if (!(dir->i_mode &S_ISVTX ))return 0 ; -if (inode->i_uid == current->fsuid) +if (inode->i_uid ==current_fsuid ())return 0 ; -if (dir->i_uid == current->fsuid) +if (dir->i_uid ==current_fsuid ())return 0 ;return !capable (CAP_FOWNER ); }
fs/nfsd/vfs.c +2 -2
@@ -1857,7 +1857,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,IS_APPEND (inode)?" append" :"" , IS_RDONLY(inode)? " ro" : "");dprintk (" owner %d/%d user %d/%d\n" , - inode->i_uid, inode->i_gid, current->fsuid, current->fsgid); + inode->i_uid, inode->i_gid,current_fsuid (), current->fsgid);#endif /* Normally we reject any write/sattr etc access on a read-only file
@@ -1899,7 +1899,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,* with NFSv3. */ if ((acc &MAY_OWNER_OVERRIDE ) && - inode->i_uid == current->fsuid) + inode->i_uid ==current_fsuid ())return 0 ; err =permission (inode, acc & (MAY_READ |MAY_WRITE |MAY_EXEC ),NULL );
fs/ocfs2/dlm/dlmfs.c +4 -4
@@ -328,8 +328,8 @@ static struct inode *dlmfs_get_root_inode(struct super_block *sb) ip =DLMFS_I (inode); inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_blocks =0 ; inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime =CURRENT_TIME ;
@@ -354,8 +354,8 @@ static struct inode *dlmfs_get_inode(struct inode *parent,return NULL ; inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_blocks =0 ; inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime =CURRENT_TIME ;
fs/ocfs2/namei.c +2 -2
@@ -426,13 +426,13 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, fe->i_blkno =cpu_to_le64 (fe_blkno); fe->i_suballoc_bit =cpu_to_le16 (suballoc_bit); fe->i_suballoc_slot =cpu_to_le16 (osb->slot_num); - fe->i_uid =cpu_to_le32 (current->fsuid); + fe->i_uid =cpu_to_le32 (current_fsuid ());if (dir->i_mode &S_ISGID ) { fe->i_gid =cpu_to_le32 (dir->i_gid);if (S_ISDIR (mode)) mode |=S_ISGID ; }else - fe->i_gid =cpu_to_le32 (current->fsgid); + fe->i_gid =cpu_to_le32 (current_fsgid ()); fe->i_mode =cpu_to_le16 (mode);if (S_ISCHR (mode) ||S_ISBLK (mode)) fe->id1.dev1.i_rdev =cpu_to_le64 (huge_encode_dev (dev));
fs/pipe.c +2 -2
@@ -938,8 +938,8 @@ static struct inode * get_pipe_inode(void)*/ inode->i_state =I_DIRTY ; inode->i_mode =S_IFIFO |S_IRUSR |S_IWUSR ; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_atime = inode->i_mtime = inode->i_ctime =CURRENT_TIME ;return inode;
fs/posix_acl.c +2 -2
@@ -217,11 +217,11 @@ posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)switch (pa->e_tag) {case ACL_USER_OBJ :/* (May have been checked already) */ -if (inode->i_uid == current->fsuid) +if (inode->i_uid ==current_fsuid ()) goto check_perm;break ;case ACL_USER : -if (pa->e_id == current->fsuid) +if (pa->e_id ==current_fsuid ()) goto mask;break ;case ACL_GROUP_OBJ :
fs/ramfs/inode.c +2 -2
@@ -55,8 +55,8 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)if (inode) { inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_blocks =0 ; inode->i_mapping->a_ops = &ramfs_aops; inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
fs/reiserfs/namei.c +2 -2
@@ -582,7 +582,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)/* the quota init calls have to know who to charge the quota to, so ** we have to set uid and gid here */ - inode->i_uid = current->fsuid; + inode->i_uid =current_fsuid (); inode->i_mode = mode;/* Make inode invalid - just in case we are going to drop it before * the initialization happens */
@@ -593,7 +593,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)if (S_ISDIR (mode)) inode->i_mode |=S_ISGID ; }else { - inode->i_gid = current->fsgid; + inode->i_gid =current_fsgid (); }DQUOT_INIT (inode);return 0 ;
fs/sysv/ialloc.c +2 -2
@@ -165,9 +165,9 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)if (S_ISDIR (mode)) mode |=S_ISGID ; }else - inode->i_gid = current->fsgid; + inode->i_gid =current_fsgid (); - inode->i_uid = current->fsuid; + inode->i_uid =current_fsuid (); inode->i_ino =fs16_to_cpu (sbi, ino); inode->i_mtime = inode->i_atime = inode->i_ctime =CURRENT_TIME_SEC ; inode->i_blocks =0 ;
fs/udf/ialloc.c +2 -2
@@ -105,13 +105,13 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)mark_buffer_dirty (UDF_SB_LVIDBH (sb)); } inode->i_mode = mode; - inode->i_uid = current->fsuid; + inode->i_uid =current_fsuid ();if (dir->i_mode &S_ISGID ) { inode->i_gid = dir->i_gid;if (S_ISDIR (mode)) mode |=S_ISGID ; }else { - inode->i_gid = current->fsgid; + inode->i_gid =current_fsgid (); }UDF_I_LOCATION (inode).logicalBlockNum = block;
fs/udf/namei.c +1 -1
@@ -636,7 +636,7 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,if (!inode) goto out; - inode->i_uid = current->fsuid; + inode->i_uid =current_fsuid ();init_special_inode (inode, mode, rdev);if (!(fi =udf_add_entry (dir, dentry, &fibh, &cfi, &err))) { inode->i_nlink--;
fs/ufs/ialloc.c +2 -2
@@ -304,13 +304,13 @@ cg_found: inode->i_ino = cg * uspi->s_ipg + bit; inode->i_mode = mode; - inode->i_uid = current->fsuid; + inode->i_uid =current_fsuid ();if (dir->i_mode &S_ISGID ) { inode->i_gid = dir->i_gid;if (S_ISDIR (mode)) inode->i_mode |=S_ISGID ; }else - inode->i_gid = current->fsgid; + inode->i_gid =current_fsgid (); inode->i_blocks =0 ; inode->i_generation =0 ;
fs/xfs/linux-2.6/xfs_linux.h +2 -2
@@ -126,8 +126,8 @@#define current_cpu () (raw_smp_processor_id())#define current_pid () (current->pid) -#define current_fsuid (cred) (current->fsuid) -#define current_fsgid (cred) (current->fsgid) +#define this_fsuid (cred) (current_fsuid()) +#define this_fsgid (cred) (current_fsgid())#define current_test_flags (f) (current->flags & (f))#define current_set_flags_nested (sp, f) \ (*(sp) = current->flags, current->flags |= (f))
fs/xfs/xfs_acl.c +3 -3
@@ -386,7 +386,7 @@ xfs_acl_allow_set( error =xfs_getattr (ip, &va,0 );if (error)return error; -if (va.va_uid != current->fsuid && !capable (CAP_FOWNER )) +if (va.va_uid !=current_fsuid () && !capable (CAP_FOWNER ))return EPERM ;return error; }
@@ -460,13 +460,13 @@ xfs_acl_access(switch (fap->acl_entry[i].ae_tag) {case ACL_USER_OBJ : seen_userobj =1 ; -if (fuid != current->fsuid) +if (fuid !=current_fsuid ())continue ; matched.ae_tag =ACL_USER_OBJ ; matched.ae_perm = allows;break ;case ACL_USER : -if (fap->acl_entry[i].ae_id != current->fsuid) +if (fap->acl_entry[i].ae_id !=current_fsuid ())continue ; matched.ae_tag =ACL_USER ; matched.ae_perm = allows;
fs/xfs/xfs_attr.c +1 -1
@@ -2627,7 +2627,7 @@ attr_user_capable( !capable(CAP_SYS_ADMIN))return -EPERM ;if (S_ISDIR (inode->i_mode) && (inode->i_mode &S_ISVTX ) && - (current_fsuid (cred) != inode->i_uid) && !capable (CAP_FOWNER )) + (this_fsuid (cred) != inode->i_uid) && !capable (CAP_FOWNER ))return -EPERM ;return 0 ; }
fs/xfs/xfs_inode.c +3 -3
@@ -1132,8 +1132,8 @@ xfs_ialloc( ip->i_d.di_onlink =0 ; ip->i_d.di_nlink = nlink;ASSERT (ip->i_d.di_nlink == nlink); - ip->i_d.di_uid =current_fsuid (cr); - ip->i_d.di_gid =current_fsgid (cr); + ip->i_d.di_uid =this_fsuid (cr); + ip->i_d.di_gid =this_fsgid (cr); ip->i_d.di_projid = prid;memset (&(ip->i_d.di_pad[0 ]),0 ,sizeof (ip->i_d.di_pad));
@@ -3642,7 +3642,7 @@ xfs_iaccess(if ((error =_ACL_XFS_IACCESS (ip, mode, cr)) !=-1 )return error ?XFS_ERROR (error) :0 ; -if (current_fsuid (cr) != ip->i_d.di_uid) { +if (this_fsuid (cr) != ip->i_d.di_uid) { mode >>=3 ;if (!in_group_p ((gid_t )ip->i_d.di_gid)) mode >>=3 ;
fs/xfs/xfs_vnodeops.c +4 -4
@@ -341,7 +341,7 @@ xfs_setattr(xfs_ilock (ip, lock_flags);/* boolean: are we the file owner? */ - file_owner = (current_fsuid (credp) == ip->i_d.di_uid); + file_owner = (this_fsuid (credp) == ip->i_d.di_uid);/* * Change various properties of a file.
@@ -1878,7 +1878,7 @@ xfs_create(* Make sure that we have allocated dquot(s) on disk. */ error =XFS_QM_DQVOPALLOC (mp, dp, -current_fsuid (credp),current_fsgid (credp), prid, +this_fsuid (credp),this_fsgid (credp), prid,XFS_QMOPT_QUOTALL |XFS_QMOPT_INHERIT , &udqp, &gdqp);if (error) goto std_return;
@@ -2757,7 +2757,7 @@ xfs_mkdir(* Make sure that we have allocated dquot(s) on disk. */ error =XFS_QM_DQVOPALLOC (mp, dp, -current_fsuid (credp),current_fsgid (credp), prid, +this_fsuid (credp),this_fsgid (credp), prid,XFS_QMOPT_QUOTALL |XFS_QMOPT_INHERIT , &udqp, &gdqp);if (error) goto std_return;
@@ -3249,7 +3249,7 @@ xfs_symlink(* Make sure that we have allocated dquot(s) on disk. */ error =XFS_QM_DQVOPALLOC (mp, dp, -current_fsuid (credp),current_fsgid (credp), prid, +this_fsuid (credp),this_fsgid (credp), prid,XFS_QMOPT_QUOTALL |XFS_QMOPT_INHERIT , &udqp, &gdqp);if (error) goto std_return;
include/linux/fs.h +1 -1
@@ -1057,7 +1057,7 @@ enum {#define has_fs_excl () atomic_read(¤t->fs_excl)#define is_owner_or_cap (inode) \ - ((current->fsuid == (inode)->i_uid) || capable(CAP_FOWNER)) + ((current_fsuid() == (inode)->i_uid) || capable(CAP_FOWNER))/* not quite ready to be deprecated, but... */ extern void lock_super (struct super_block *);
include/linux/sched.h +3 -0
@@ -1180,6 +1180,9 @@ struct task_struct {struct prop_local_single dirties; }; +#define current_fsuid () (current->fsuid) +#define current_fsgid () (current->fsgid) +/* * Priority of a process goes from 0..MAX_PRIO-1, valid RT * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
ipc/mqueue.c +2 -2
@@ -109,8 +109,8 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode, inode =new_inode (sb);if (inode) { inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_blocks =0 ; inode->i_mtime = inode->i_ctime = inode->i_atime =CURRENT_TIME ;
kernel/cgroup.c +2 -2
@@ -577,8 +577,8 @@ static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)if (inode) { inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_blocks =0 ; inode->i_atime = inode->i_mtime = inode->i_ctime =CURRENT_TIME ; inode->i_mapping->backing_dev_info = &cgroup_backing_dev_info;
mm/shmem.c +4 -4
@@ -1412,8 +1412,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) inode =new_inode (sb);if (inode) { inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid (); inode->i_blocks =0 ; inode->i_mapping->a_ops = &shmem_aops; inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
@@ -2241,8 +2241,8 @@ static int shmem_fill_super(struct super_block *sb,struct inode *inode;struct dentry *root;int mode =S_IRWXUGO |S_ISVTX ; -uid_t uid = current->fsuid; -gid_t gid = current->fsgid; +uid_t uid =current_fsuid (); +gid_t gid =current_fsgid ();int err = -ENOMEM ;struct shmem_sb_info *sbinfo;unsigned long blocks =0 ;
net/9p/client.c +1 -1
@@ -938,7 +938,7 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt) fid->rdir_fpos =0 ; fid->rdir_pos =0 ; fid->rdir_fcall =NULL ; - fid->uid = current->fsuid; + fid->uid =current_fsuid (); fid->clnt = clnt; fid->aux =NULL ;
net/socket.c +2 -2
@@ -484,8 +484,8 @@ static struct socket *sock_alloc(void) sock =SOCKET_I (inode); inode->i_mode =S_IFSOCK |S_IRWXUGO ; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid =current_fsuid (); + inode->i_gid =current_fsgid ();get_cpu_var (sockets_in_use)++;put_cpu_var (sockets_in_use);
net/sunrpc/auth.c +4 -4
@@ -337,8 +337,8 @@ struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *auth, int flags) {struct auth_cred acred = { - .uid = current->fsuid, - .gid = current->fsgid, + .uid =current_fsuid (), + .gid =current_fsgid (), .group_info = current->group_info, };struct rpc_cred *ret;
@@ -373,8 +373,8 @@ rpcauth_bindcred(struct rpc_task *task) {struct rpc_auth *auth = task->tk_client->cl_auth;struct auth_cred acred = { - .uid = current->fsuid, - .gid = current->fsgid, + .uid =current_fsuid (), + .gid =current_fsgid (), .group_info = current->group_info, };struct rpc_cred *ret;
security/commoncap.c +4 -4
@@ -336,8 +336,8 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) } } - current->suid = current->euid = current->fsuid = bprm->e_uid; - current->sgid = current->egid = current->fsgid = bprm->e_gid; + current->suid = current->euid =current_fsuid () = bprm->e_uid; + current->sgid = current->egid =current_fsgid () = bprm->e_gid;/* For init, we want to retain the capabilities set * in the init_task struct. Thus we skip the usual
@@ -466,11 +466,11 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,*/ if (!issecure (SECURE_NO_SETUID_FIXUP )) { -if (old_fsuid ==0 && current->fsuid !=0 ) { +if (old_fsuid ==0 &¤t_fsuid () !=0 ) {cap_t (current->cap_effective) &= ~CAP_FS_MASK ; } -if (old_fsuid !=0 && current->fsuid ==0 ) { +if (old_fsuid !=0 &¤t_fsuid () ==0 ) {cap_t (current->cap_effective) |= (cap_t (current->cap_permitted) &CAP_FS_MASK );
security/keys/key.c +1 -1
@@ -817,7 +817,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, perm |=KEY_USR_WRITE ;/* allocate a new key */ - key =key_alloc (ktype, description, current->fsuid, current->fsgid, + key =key_alloc (ktype, description,current_fsuid (), current->fsgid, current, perm, flags);if (IS_ERR (key)) { key_ref =ERR_PTR (PTR_ERR (key));
security/keys/keyctl.c +1 -1
@@ -810,7 +810,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)down_write (&key->sem);/* if we're not the sysadmin, we can only change a key that we own */ -if (capable (CAP_SYS_ADMIN ) || key->uid == current->fsuid) { +if (capable (CAP_SYS_ADMIN ) || key->uid ==current_fsuid ()) { key->perm = perm; ret =0 ; }
security/keys/request_key.c +5 -5
@@ -76,7 +76,7 @@ static int call_sbin_request_key(struct key_construction *cons,/* allocate a new session keyring */ sprintf (desc,"_req.%u" , key->serial); - keyring =keyring_alloc (desc, current->fsuid, current->fsgid, current, + keyring =keyring_alloc (desc,current_fsuid (), current->fsgid, current,KEY_ALLOC_QUOTA_OVERRUN ,NULL );if (IS_ERR (keyring)) { ret =PTR_ERR (keyring);
@@ -89,8 +89,8 @@ static int call_sbin_request_key(struct key_construction *cons, goto error_link;/* record the UID and GID */ -sprintf (uid_str,"%d" , current->fsuid); -sprintf (gid_str,"%d" , current->fsgid); +sprintf (uid_str,"%d" ,current_fsuid ()); +sprintf (gid_str,"%d" ,current_fsgid ());/* we say which key is under construction */ sprintf (key_str,"%d" , key->serial);
@@ -278,7 +278,7 @@ static int construct_alloc_key(struct key_type *type,mutex_lock (&user->cons_lock); key =key_alloc (type, description, - current->fsuid, current->fsgid, current,KEY_POS_ALL , +current_fsuid (), current->fsgid, current,KEY_POS_ALL , flags);if (IS_ERR (key)) goto alloc_failed;
@@ -341,7 +341,7 @@ static struct key *construct_key_and_link(struct key_type *type,struct key *key;int ret; - user =key_user_lookup (current->fsuid); + user =key_user_lookup (current_fsuid ());if (!user)return ERR_PTR (-ENOMEM );
security/keys/request_key_auth.c +1 -1
@@ -194,7 +194,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,sprintf (desc,"%x" , target->serial); authkey =key_alloc (&key_type_request_key_auth, desc, - current->fsuid, current->fsgid, current, +current_fsuid (), current->fsgid, current,KEY_POS_VIEW |KEY_POS_READ |KEY_POS_SEARCH |KEY_USR_VIEW ,KEY_ALLOC_NOT_IN_QUOTA );if (IS_ERR (authkey)) {
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 6/26 Security: Separate task security context from task_struct
In reply to David HowellsSeparate the task security context from task_struct. At this point, the security data is temporarily embedded in the task_struct with two pointers pointing to it.
---
drivers/block/loop.c | 5 - drivers/char/agp/frontend.c | 2 drivers/char/drm/drm_fops.c | 2 drivers/char/tty_audit.c | 2 fs/affs/super.c | 4 - fs/autofs/inode.c | 4 - fs/autofs4/inode.c | 4 - fs/autofs4/waitq.c | 4 - fs/binfmt_elf.c | 12 +- fs/cifs/connect.c | 5 - fs/cifs/ioctl.c | 2 fs/ecryptfs/messaging.c | 15 +- fs/exec.c | 20 ++- fs/fat/inode.c | 4 - fs/fcntl.c | 7 + fs/file_table.c | 4 - fs/fuse/dir.c | 12 +- fs/hfs/super.c | 4 - fs/hfsplus/options.c | 4 - fs/hpfs/super.c | 4 - fs/hugetlbfs/inode.c | 4 - fs/inotify_user.c | 2 fs/ioprio.c | 12 +- fs/namei.c | 6 + fs/ncpfs/ioctl.c | 32 ++--- fs/open.c | 22 ++- fs/proc/array.c | 14 +- fs/proc/base.c | 16 +- fs/proc/proc_sysctl.c | 4 - fs/quota.c | 4 - fs/smbfs/dir.c | 4 - fs/smbfs/inode.c | 2 fs/smbfs/proc.c | 2 include/linux/init_task.h | 23 +++ include/linux/sched.h | 78 +++++++++--- include/net/scm.h | 4 - ipc/mqueue.c | 4 - ipc/msg.c | 4 - ipc/sem.c | 4 - ipc/shm.c | 16 +- ipc/util.c | 7 + kernel/acct.c | 8 + kernel/auditsc.c | 40 +++--- kernel/cgroup.c | 5 - kernel/exit.c | 12 +- kernel/fork.c | 23 ++- kernel/futex.c | 8 + kernel/futex_compat.c | 5 - kernel/ptrace.c | 14 +- kernel/sched.c | 9 + kernel/signal.c | 26 ++-- kernel/sys.c | 251 ++++++++++++++++++++------------------ kernel/sysctl.c | 2 kernel/timer.c | 8 + kernel/uid16.c | 28 ++-- kernel/user.c | 4 - kernel/user_namespace.c | 2 mm/oom_kill.c | 6 - net/core/scm.c | 10 +- net/sunrpc/auth.c | 4 - net/unix/af_unix.c | 12 +- security/commoncap.c | 110 ++++++++++------- security/dummy.c | 40 ++++-- security/keys/key.c | 2 security/keys/keyctl.c | 25 ++-- security/keys/permission.c | 11 +- security/keys/process_keys.c | 76 ++++++------ security/keys/request_key.c | 17 +-- security/keys/request_key_auth.c | 14 +- security/selinux/exports.c | 4 - security/selinux/hooks.c | 111 ++++++++--------- security/selinux/selinuxfs.c | 2 72 files changed, 698 insertions(+), 575 deletions(-)
drivers/block/loop.c +3 -2
@@ -928,7 +928,8 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)int err;struct loop_func_table *xfer; -if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid && +if (lo->lo_encrypt_key_size && + lo->lo_key_owner != current->act_as->uid && !capable (CAP_SYS_ADMIN ))return -EPERM ;if (lo->lo_state != Lo_bound)
@@ -979,7 +980,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)if (info->lo_encrypt_key_size) {memcpy (lo->lo_encrypt_key, info->lo_encrypt_key, info->lo_encrypt_key_size); - lo->lo_key_owner = current->uid; + lo->lo_key_owner = current->act_as->uid; }return 0 ;
drivers/char/agp/frontend.c +1 -1
@@ -689,7 +689,7 @@ static int agp_open(struct inode *inode, struct file *file)set_bit (AGP_FF_ALLOW_CLIENT , &priv->access_flags); priv->my_pid = current->pid; -if ((current->uid ==0 ) || (current->suid ==0 )) { +if ((current->act_as->uid ==0 ) || (current->act_as->suid ==0 )) {/* Root priv, can be controller */ set_bit (AGP_FF_ALLOW_CONTROLLER , &priv->access_flags); }
drivers/char/drm/drm_fops.c +1 -1
@@ -243,7 +243,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,memset (priv,0 ,sizeof (*priv)); filp->private_data = priv; priv->filp = filp; - priv->uid = current->euid; + priv->uid = current->act_as->euid; priv->pid =task_pid_nr (current); priv->minor = minor; priv->head = drm_heads[minor];
drivers/char/tty_audit.c +1 -1
@@ -86,7 +86,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,char name[sizeof (tsk->comm)];audit_log_format (ab,"tty pid=%u uid=%u auid=%u major=%d " -"minor=%d comm=" , tsk->pid, tsk->uid, +"minor=%d comm=" , tsk->pid, tsk->sec->uid, loginuid, buf->major, buf->minor);get_task_comm (name, tsk);audit_log_untrustedstring (ab, name);
fs/affs/super.c +2 -2
@@ -159,8 +159,8 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s/* Fill in defaults */ - *uid = current->uid; - *gid = current->gid; + *uid = current->sec->uid; + *gid = current->sec->gid; *reserved =2 ; *root =-1 ; *blocksize =-1 ;
fs/autofs/inode.c +2 -2
@@ -78,8 +78,8 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,substring_t args[MAX_OPT_ARGS ];int option; - *uid = current->uid; - *gid = current->gid; + *uid = current->sec->uid; + *gid = current->sec->gid; *pgrp =task_pgrp_nr (current); *minproto = *maxproto =AUTOFS_PROTO_VERSION ;
fs/autofs4/inode.c +2 -2
@@ -224,8 +224,8 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,substring_t args[MAX_OPT_ARGS ];int option; - *uid = current->uid; - *gid = current->gid; + *uid = current->sec->uid; + *gid = current->sec->gid; *pgrp =task_pgrp_nr (current); *minproto =AUTOFS_MIN_PROTO_VERSION ;
fs/autofs4/waitq.c +2 -2
@@ -294,8 +294,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, wq->len = len; wq->dev =autofs4_get_dev (sbi); wq->ino =autofs4_get_ino (sbi); - wq->uid = current->uid; - wq->gid = current->gid; + wq->uid = current->sec->uid; + wq->gid = current->sec->gid; wq->pid = current->pid; wq->tgid = current->tgid; wq->status = -EINTR ;/* Status return if interrupted */
fs/binfmt_elf.c +6 -6
@@ -200,10 +200,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,NEW_AUX_ENT (AT_BASE , interp_load_addr);NEW_AUX_ENT (AT_FLAGS ,0 );NEW_AUX_ENT (AT_ENTRY , exec->e_entry); -NEW_AUX_ENT (AT_UID , tsk->uid); -NEW_AUX_ENT (AT_EUID , tsk->euid); -NEW_AUX_ENT (AT_GID , tsk->gid); -NEW_AUX_ENT (AT_EGID , tsk->egid); +NEW_AUX_ENT (AT_UID , tsk->sec->uid); +NEW_AUX_ENT (AT_EUID , tsk->sec->euid); +NEW_AUX_ENT (AT_GID , tsk->sec->gid); +NEW_AUX_ENT (AT_EGID , tsk->sec->egid);NEW_AUX_ENT (AT_SECURE ,security_bprm_secureexec (bprm));if (k_platform) { NEW_AUX_ENT(AT_PLATFORM,
@@ -1440,8 +1440,8 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, psinfo->pr_zomb = psinfo->pr_sname =='Z' ; psinfo->pr_nice =task_nice (p); psinfo->pr_flag = p->flags; -SET_UID (psinfo->pr_uid, p->uid); -SET_GID (psinfo->pr_gid, p->gid); +SET_UID (psinfo->pr_uid, p->sec->uid); +SET_GID (psinfo->pr_gid, p->sec->gid);strncpy (psinfo->pr_fname, p->comm,sizeof (psinfo->pr_fname));return 0 ;
fs/cifs/connect.c +3 -2
@@ -818,8 +818,9 @@ cifs_parse_mount_options(char *options, const char *devname,/* null target name indicates to use *SMBSERVR default called name if we end up sending RFC1001 session initialize */ vol->target_rfc1001_name[0 ] =0 ; - vol->linux_uid = current->uid;/* current->euid instead? */ - vol->linux_gid = current->gid; + vol->linux_uid = current->sec->uid;/* use current->act_as->euid +* instead? */ + vol->linux_gid = current->sec->gid; vol->dir_mode =S_IRWXUGO ;/* 2767 perms indicate mandatory locking support */ vol->file_mode = (S_IRWXUGO |S_ISGID ) & (~S_IXGRP );
fs/cifs/ioctl.c +1 -1
@@ -65,7 +65,7 @@ int cifs_ioctl (struct inode *inode, struct file *filep,switch (command) {case CIFS_IOC_CHECKUMOUNT :cFYI (1 , ("User unmount attempted" )); -if (cifs_sb->mnt_uid == current->uid) +if (cifs_sb->mnt_uid == current->sec->uid) rc =0 ;else { rc = -EACCES ;
fs/ecryptfs/messaging.c +8 -7
@@ -264,26 +264,27 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid, } msg_ctx = &ecryptfs_msg_ctx_arr[msg->index];mutex_lock (&msg_ctx->mux); -if (ecryptfs_find_daemon_id (msg_ctx->task->euid, &id)) { +if (ecryptfs_find_daemon_id (msg_ctx->task->sec->euid, &id)) { rc = -EBADMSG ;ecryptfs_printk (KERN_WARNING ,"User [%d] received a " "message response from process [%d] but does " "not have a registered daemon\n" , - msg_ctx->task->euid, pid); + msg_ctx->task->sec->euid, pid); goto wake_up; } -if (msg_ctx->task->euid != uid) { +if (msg_ctx->task->sec->euid != uid) { rc = -EBADMSG ;ecryptfs_printk (KERN_WARNING ,"Received message from user " "[%d]; expected message from user [%d]\n" , - uid, msg_ctx->task->euid); + uid, msg_ctx->task->sec->euid); goto unlock; }if (id->pid != pid) { rc = -EBADMSG ;ecryptfs_printk (KERN_ERR ,"User [%d] received a " "message response from an unrecognized " -"process [%d]\n" , msg_ctx->task->euid, pid); +"process [%d]\n" , + msg_ctx->task->sec->euid, pid); goto unlock; }if (msg_ctx->state !=ECRYPTFS_MSG_CTX_STATE_PENDING ) {
@@ -331,11 +332,11 @@ int ecryptfs_send_message(unsigned int transport, char *data, int data_len,int rc;mutex_lock (&ecryptfs_daemon_id_hash_mux); -if (ecryptfs_find_daemon_id (current->euid, &id)) { +if (ecryptfs_find_daemon_id (current->act_as->euid, &id)) {mutex_unlock (&ecryptfs_daemon_id_hash_mux); rc = -ENOTCONN ;ecryptfs_printk (KERN_ERR ,"User [%d] does not have a daemon " -"registered\n" , current->euid); +"registered\n" , current->sec->euid); goto out; }mutex_unlock (&ecryptfs_daemon_id_hash_mux);
fs/exec.c +11 -9
@@ -1000,7 +1000,8 @@ int flush_old_exec(struct linux_binprm * bprm) current->sas_ss_sp = current->sas_ss_size =0 ; -if (current->euid == current->uid && current->egid == current->gid) +if (current->sec->euid == current->sec->uid && + current->sec->egid == current->sec->gid)set_dumpable (current->mm,1 );else set_dumpable (current->mm, suid_dumpable);
@@ -1027,7 +1028,8 @@ int flush_old_exec(struct linux_binprm * bprm)*/ current->mm->task_size =TASK_SIZE ; -if (bprm->e_uid != current->euid || bprm->e_gid != current->egid) { +if (bprm->e_uid != current->sec->euid || + bprm->e_gid != current->sec->egid) {suid_keys (current);set_dumpable (current->mm, suid_dumpable); current->pdeath_signal =0 ;
@@ -1069,8 +1071,8 @@ int prepare_binprm(struct linux_binprm *bprm)if (bprm->file->f_op ==NULL )return -EACCES ; - bprm->e_uid = current->euid; - bprm->e_gid = current->egid; + bprm->e_uid = current->sec->euid; + bprm->e_gid = current->sec->egid;if (!(bprm->file->f_path.mnt->mnt_flags &MNT_NOSUID )) {/* Set-uid? */
@@ -1123,7 +1125,7 @@ void compute_creds(struct linux_binprm *bprm) {int unsafe; -if (bprm->e_uid != current->uid) { +if (bprm->e_uid != current->sec->uid) {suid_keys (current); current->pdeath_signal =0 ; }
@@ -1441,7 +1443,7 @@ static int format_corename(char *corename, const char *pattern, long signr)/* uid */ case 'u' : rc =snprintf (out_ptr, out_end - out_ptr, -"%d" , current->uid); +"%d" , current->sec->uid);if (rc > out_end - out_ptr) goto out; out_ptr += rc;
@@ -1449,7 +1451,7 @@ static int format_corename(char *corename, const char *pattern, long signr)/* gid */ case 'g' : rc =snprintf (out_ptr, out_end - out_ptr, -"%d" , current->gid); +"%d" , current->sec->gid);if (rc > out_end - out_ptr) goto out; out_ptr += rc;
@@ -1707,7 +1709,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)*/ if (get_dumpable (mm) ==2 ) {/* Setuid core dump mode */ flag =O_EXCL ;/* Stop rewrite attacks */ - current->fsuid =0 ;/* Dump root private */ + current->act_as->fsuid =0 ;/* Dump root private */ } retval =coredump_wait (exit_code);
@@ -1803,7 +1805,7 @@ fail_unlock:if (helper_argv)argv_free (helper_argv); - current->fsuid = fsuid; + current->act_as->fsuid = fsuid;complete_all (&mm->core_done); fail:return retval;
fs/fat/inode.c +2 -2
@@ -934,8 +934,8 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, opts->isvfat = is_vfat; - opts->fs_uid = current->uid; - opts->fs_gid = current->gid; + opts->fs_uid = current->sec->uid; + opts->fs_gid = current->sec->gid; opts->fs_fmask = opts->fs_dmask = current->fs->umask; opts->codepage = fat_default_codepage; opts->iocharset = fat_default_iocharset;
fs/fcntl.c +4 -3
@@ -276,7 +276,8 @@ int __f_setown(struct file *filp, struct pid *pid, enum pid_type type,if (err)return err; -f_modown (filp, pid, type, current->uid, current->euid, force); +f_modown (filp, pid, type, current->sec->uid, current->act_as->euid, + force);return 0 ; }EXPORT_SYMBOL (__f_setown);
@@ -461,8 +462,8 @@ static inline int sigio_perm(struct task_struct *p, struct fown_struct *fown, int sig) {return (((fown->euid ==0 ) || - (fown->euid == p->suid) || (fown->euid == p->uid) || - (fown->uid == p->suid) || (fown->uid == p->uid)) && + (fown->euid == p->sec->suid) || (fown->euid == p->sec->uid) || + (fown->uid == p->sec->suid) || (fown->uid == p->sec->uid)) && !security_file_send_sigiotask (p, fown, sig)); }
fs/file_table.c +2 -2
@@ -114,8 +114,8 @@ struct file *get_empty_filp(void)INIT_LIST_HEAD (&f->f_u.fu_list);atomic_set (&f->f_count,1 );rwlock_init (&f->f_owner.lock); - f->f_uid = tsk->fsuid; - f->f_gid = tsk->fsgid; + f->f_uid = tsk->act_as->fsuid; + f->f_gid = tsk->act_as->fsgid;eventpoll_init_file (f);/* f->f_version: 0 */ return f;
fs/fuse/dir.c +6 -6
@@ -830,12 +830,12 @@ int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)if (fc->flags &FUSE_ALLOW_OTHER )return 1 ; -if (task->euid == fc->user_id && - task->suid == fc->user_id && - task->uid == fc->user_id && - task->egid == fc->group_id && - task->sgid == fc->group_id && - task->gid == fc->group_id) +if (task->sec->euid == fc->user_id && + task->sec->suid == fc->user_id && + task->sec->uid == fc->user_id && + task->sec->egid == fc->group_id && + task->sec->sgid == fc->group_id && + task->sec->gid == fc->group_id)return 1 ;return 0 ;
fs/hfs/super.c +2 -2
@@ -210,8 +210,8 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)int tmp, token;/* initialize the sb with defaults */ - hsb->s_uid = current->uid; - hsb->s_gid = current->gid; + hsb->s_uid = current->sec->uid; + hsb->s_gid = current->sec->gid; hsb->s_file_umask =0133 ; hsb->s_dir_umask =0022 ; hsb->s_type = hsb->s_creator =cpu_to_be32 (0x3f3f3f3f );/* == '????' */
fs/hfsplus/options.c +2 -2
@@ -49,8 +49,8 @@ void hfsplus_fill_defaults(struct hfsplus_sb_info *opts) opts->creator =HFSPLUS_DEF_CR_TYPE ; opts->type =HFSPLUS_DEF_CR_TYPE ; opts->umask = current->fs->umask; - opts->uid = current->uid; - opts->gid = current->gid; + opts->uid = current->sec->uid; + opts->gid = current->sec->gid; opts->part =-1 ; opts->session =-1 ; }
fs/hpfs/super.c +2 -2
@@ -464,8 +464,8 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)init_MUTEX (&sbi->hpfs_creation_de); - uid = current->uid; - gid = current->gid; + uid = current->sec->uid; + gid = current->sec->gid; umask = current->fs->umask; lowercase =0 ; conv =CONV_BINARY ;
fs/hugetlbfs/inode.c +2 -2
@@ -921,7 +921,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size)if (!can_do_hugetlb_shm ())return ERR_PTR (-EPERM ); -if (!user_shm_lock (size, current->user)) +if (!user_shm_lock (size, current->sec->user))return ERR_PTR (-ENOMEM ); root = hugetlbfs_vfsmount->mnt_root;
@@ -960,7 +960,7 @@ out_inode: out_dentry:dput (dentry); out_shm_unlock: -user_shm_unlock (size, current->user); +user_shm_unlock (size, current->sec->user);return ERR_PTR (error); }
fs/inotify_user.c +1 -1
@@ -558,7 +558,7 @@ asmlinkage long sys_inotify_init(void) goto out_put_fd; } - user =get_uid (current->user); + user =get_uid (current->sec->user);if (unlikely (atomic_read (&user->inotify_devs) >= inotify_max_user_instances)) { ret = -EMFILE ;
fs/ioprio.c +6 -6
@@ -32,8 +32,8 @@ static int set_task_ioprio(struct task_struct *task, int ioprio)int err;struct io_context *ioc; -if (task->uid != current->euid && - task->uid != current->uid && !capable (CAP_SYS_NICE )) +if (task->sec->uid != current->act_as->euid && + task->sec->uid != current->act_as->uid && !capable (CAP_SYS_NICE ))return -EPERM ; err =security_task_setioprio (task, ioprio);
@@ -115,7 +115,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)break ;case IOPRIO_WHO_USER :if (!who) - user = current->user; + user = current->sec->user;else user =find_user (who);
@@ -123,7 +123,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)break ; do_each_thread(g, p) { -if (p->uid != who) +if (p->sec->uid != who)continue ; ret =set_task_ioprio (p, ioprio);if (ret)
@@ -206,7 +206,7 @@ asmlinkage long sys_ioprio_get(int which, int who)break ;case IOPRIO_WHO_USER :if (!who) - user = current->user; + user = current->sec->user;else user =find_user (who);
@@ -214,7 +214,7 @@ asmlinkage long sys_ioprio_get(int which, int who)break ; do_each_thread(g, p) { -if (p->uid != user->uid) +if (p->sec->uid != user->uid)continue ; tmpio =get_task_ioprio (p);if (tmpio <0 )
fs/namei.c +4 -2
@@ -1433,11 +1433,13 @@ int fastcall __user_walk(const char __user *name, unsigned flags, struct nameida*/ static inline int check_sticky (struct inode *dir,struct inode *inode) { +uid_t fsuid = current->act_as->fsuid; +if (!(dir->i_mode &S_ISVTX ))return 0 ; -if (inode->i_uid ==current_fsuid ()) +if (inode->i_uid == fsuid)return 0 ; -if (dir->i_uid ==current_fsuid ()) +if (dir->i_uid == fsuid)return 0 ;return !capable (CAP_FOWNER ); }
fs/ncpfs/ioctl.c +16 -16
@@ -40,7 +40,7 @@ ncp_get_fs_info(struct ncp_server * server, struct file *file,struct ncp_fs_info info;if ((file_permission (file,MAY_WRITE ) !=0 ) - && (current->uid != server->m.mounted_uid)) { + && (current->act_as->uid != server->m.mounted_uid)) {return -EACCES ; }if (copy_from_user (&info, arg,sizeof (info)))
@@ -70,7 +70,7 @@ ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,struct ncp_fs_info_v2 info2;if ((file_permission (file,MAY_WRITE ) !=0 ) - && (current->uid != server->m.mounted_uid)) { + && (current->act_as->uid != server->m.mounted_uid)) {return -EACCES ; }if (copy_from_user (&info2, arg,sizeof (info2)))
@@ -141,7 +141,7 @@ ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,struct compat_ncp_fs_info_v2 info2;if ((file_permission (file,MAY_WRITE ) !=0 ) - && (current->uid != server->m.mounted_uid)) { + && (current->act_as->uid != server->m.mounted_uid)) {return -EACCES ; }if (copy_from_user (&info2, arg,sizeof (info2)))
@@ -276,7 +276,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,#endif case NCP_IOC_NCPREQUEST :if ((file_permission (filp,MAY_WRITE ) !=0 ) - && (current->uid != server->m.mounted_uid)) { + && (current->act_as->uid != server->m.mounted_uid)) {return -EACCES ; }#ifdef CONFIG_COMPAT
@@ -356,7 +356,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,case NCP_IOC_GETMOUNTUID32 :case NCP_IOC_GETMOUNTUID64 :if ((file_permission (filp,MAY_READ ) !=0 ) - && (current->uid != server->m.mounted_uid)) { + && (current->act_as->uid != server->m.mounted_uid)) {return -EACCES ; }if (cmd ==NCP_IOC_GETMOUNTUID16 ) {
@@ -380,7 +380,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,struct ncp_setroot_ioctl sr;if ((file_permission (filp,MAY_READ ) !=0 ) - && (current->uid != server->m.mounted_uid)) + && (current->act_as->uid != server->m.mounted_uid)) {return -EACCES ; }
@@ -455,7 +455,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,#ifdef CONFIG_NCPFS_PACKET_SIGNING case NCP_IOC_SIGN_INIT :if ((file_permission (filp,MAY_WRITE ) !=0 ) - && (current->uid != server->m.mounted_uid)) + && (current->act_as->uid != server->m.mounted_uid)) {return -EACCES ; }
@@ -478,7 +478,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,case NCP_IOC_SIGN_WANTED :if ((file_permission (filp,MAY_READ ) !=0 ) - && (current->uid != server->m.mounted_uid)) + && (current->act_as->uid != server->m.mounted_uid)) {return -EACCES ; }
@@ -491,7 +491,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,int newstate;if ((file_permission (filp,MAY_WRITE ) !=0 ) - && (current->uid != server->m.mounted_uid)) + && (current->act_as->uid != server->m.mounted_uid)) {return -EACCES ; }
@@ -512,7 +512,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,#ifdef CONFIG_NCPFS_IOCTL_LOCKING case NCP_IOC_LOCKUNLOCK :if ((file_permission (filp,MAY_WRITE ) !=0 ) - && (current->uid != server->m.mounted_uid)) + && (current->act_as->uid != server->m.mounted_uid)) {return -EACCES ; }
@@ -585,7 +585,7 @@ outrel:#ifdef CONFIG_COMPAT case NCP_IOC_GETOBJECTNAME_32 : -if (current->uid != server->m.mounted_uid) { +if (current->act_as->uid != server->m.mounted_uid) {return -EACCES ; } {
@@ -610,7 +610,7 @@ outrel: }#endif case NCP_IOC_GETOBJECTNAME : -if (current->uid != server->m.mounted_uid) { +if (current->act_as->uid != server->m.mounted_uid) {return -EACCES ; } {
@@ -637,7 +637,7 @@ outrel:case NCP_IOC_SETOBJECTNAME_32 :#endif case NCP_IOC_SETOBJECTNAME : -if (current->uid != server->m.mounted_uid) { +if (current->act_as->uid != server->m.mounted_uid) {return -EACCES ; } {
@@ -695,7 +695,7 @@ outrel:case NCP_IOC_GETPRIVATEDATA_32 :#endif case NCP_IOC_GETPRIVATEDATA : -if (current->uid != server->m.mounted_uid) { +if (current->act_as->uid != server->m.mounted_uid) {return -EACCES ; } {
@@ -740,7 +740,7 @@ outrel:case NCP_IOC_SETPRIVATEDATA_32 :#endif case NCP_IOC_SETPRIVATEDATA : -if (current->uid != server->m.mounted_uid) { +if (current->act_as->uid != server->m.mounted_uid) {return -EACCES ; } {
@@ -795,7 +795,7 @@ outrel:case NCP_IOC_SETDENTRYTTL :if ((file_permission (filp,MAY_WRITE ) !=0 ) && - (current->uid != server->m.mounted_uid)) + current->act_as->uid != server->m.mounted_uid)return -EACCES ; {u_int32_t user;
fs/open.c +11 -11
@@ -428,12 +428,12 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)if (mode & ~S_IRWXO )/* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL ; - old_fsuid = current->fsuid; - old_fsgid = current->fsgid; - old_cap = current->cap_effective; + old_fsuid = current->act_as->fsuid; + old_fsgid = current->act_as->fsgid; + old_cap = current->act_as->cap_effective; - current->fsuid = current->uid; - current->fsgid = current->gid; + current->act_as->fsuid = current->act_as->uid; + current->act_as->fsgid = current->act_as->gid;/* * Clear the capabilities if we switch to a non-root user
@@ -443,10 +443,10 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)* value below. We should hold task_capabilities_lock, * but we cannot because user_path_walk can sleep. */ -if (current->uid) -cap_clear (current->cap_effective); +if (current->act_as->uid) +cap_clear (current->act_as->cap_effective);else - current->cap_effective = current->cap_permitted; + current->act_as->cap_effective = current->act_as->cap_permitted; res =__user_walk_fd (dfd, filename,LOOKUP_FOLLOW |LOOKUP_ACCESS , &nd);if (res)
@@ -464,9 +464,9 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) out_path_release:path_release (&nd); out: - current->fsuid = old_fsuid; - current->fsgid = old_fsgid; - current->cap_effective = old_cap; + current->act_as->fsuid = old_fsuid; + current->act_as->fsgid = old_fsgid; + current->act_as->cap_effective = old_cap;return res; }
fs/proc/array.c +7 -7
@@ -182,8 +182,8 @@ static inline char *task_state(struct task_struct *p, char *buffer)task_tgid_nr_ns (p, ns),task_pid_nr_ns (p, ns), ppid, tpid, - p->uid, p->euid, p->suid, p->fsuid, - p->gid, p->egid, p->sgid, p->fsgid); + p->sec->uid, p->sec->euid, p->sec->suid, p->sec->fsuid, + p->sec->gid, p->sec->egid, p->sec->sgid, p->sec->fsgid);task_lock (p);if (p->files)
@@ -194,7 +194,7 @@ static inline char *task_state(struct task_struct *p, char *buffer) fdt ? fdt->max_fds : 0);rcu_read_unlock (); - group_info = p->group_info; + group_info = p->sec->group_info;get_group_info (group_info);task_unlock (p);
@@ -267,7 +267,7 @@ static inline char *task_sig(struct task_struct *p, char *buffer) blocked = p->blocked;collect_sigign_sigcatch (p, &ignored, &caught); num_threads =atomic_read (&p->signal->count); - qsize =atomic_read (&p->user->sigpending); + qsize =atomic_read (&p->sec->user->sigpending); qlim = p->signal->rlim[RLIMIT_SIGPENDING ].rlim_cur;unlock_task_sighand (p, &flags); }
@@ -291,9 +291,9 @@ static inline char *task_cap(struct task_struct *p, char *buffer)return buffer +sprintf (buffer,"CapInh:\t%016x\n" "CapPrm:\t%016x\n" "CapEff:\t%016x\n" , -cap_t (p->cap_inheritable), -cap_t (p->cap_permitted), -cap_t (p->cap_effective)); +cap_t (p->sec->cap_inheritable), +cap_t (p->sec->cap_permitted), +cap_t (p->sec->cap_effective)); } static inline char *task_context_switch_counts(struct task_struct *p,
fs/proc/base.c +8 -8
@@ -1201,8 +1201,8 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st inode->i_uid =0 ; inode->i_gid =0 ;if (task_dumpable (task)) { - inode->i_uid = task->euid; - inode->i_gid = task->egid; + inode->i_uid = task->sec->euid; + inode->i_gid = task->sec->egid; }security_task_to_inode (task, inode);
@@ -1227,8 +1227,8 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstatif (task) {if ((inode->i_mode == (S_IFDIR |S_IRUGO |S_IXUGO )) ||task_dumpable (task)) { - stat->uid = task->euid; - stat->gid = task->egid; + stat->uid = task->sec->euid; + stat->gid = task->sec->egid; } }rcu_read_unlock ();
@@ -1259,8 +1259,8 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)if (task) {if ((inode->i_mode == (S_IFDIR |S_IRUGO |S_IXUGO )) ||task_dumpable (task)) { - inode->i_uid = task->euid; - inode->i_gid = task->egid; + inode->i_uid = task->sec->euid; + inode->i_gid = task->sec->egid; }else { inode->i_uid =0 ; inode->i_gid =0 ;
@@ -1433,8 +1433,8 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)rcu_read_unlock ();put_files_struct (files);if (task_dumpable (task)) { - inode->i_uid = task->euid; - inode->i_gid = task->egid; + inode->i_uid = task->sec->euid; + inode->i_gid = task->sec->egid; }else { inode->i_uid =0 ; inode->i_gid =0 ;
fs/proc/proc_sysctl.c +2 -2
@@ -393,9 +393,9 @@ static int proc_sys_permission(struct inode *inode, int mask, struct nameidata * error = -EACCES ; mode = inode->i_mode; -if (current->euid ==0 ) +if (current->act_as->euid ==0 ) mode >>=6 ; -else if (in_group_p (0 )) +else if (in_egroup_p (0 )) mode >>=3 ;if ((mode & mask & (MAY_READ |MAY_WRITE |MAY_EXEC )) == mask)
fs/quota.c +2 -2
@@ -80,7 +80,7 @@ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid/* Check privileges */ if (cmd ==Q_GETQUOTA ) { -if (((type ==USRQUOTA && current->euid != id) || +if (((type ==USRQUOTA && current->act_as->euid != id) || (type ==GRPQUOTA && !in_egroup_p (id))) && !capable (CAP_SYS_ADMIN ))return -EPERM ;
@@ -131,7 +131,7 @@ static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t i/* Check privileges */ if (cmd ==Q_XGETQUOTA ) { -if (((type ==XQM_USRQUOTA && current->euid != id) || +if (((type ==XQM_USRQUOTA && current->act_as->euid != id) || (type ==XQM_GRPQUOTA && !in_egroup_p (id))) && !capable (CAP_SYS_ADMIN ))return -EPERM ;
fs/smbfs/dir.c +2 -2
@@ -667,8 +667,8 @@ smb_make_node(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) attr.ia_valid =ATTR_MODE |ATTR_UID |ATTR_GID ; attr.ia_mode = mode; - attr.ia_uid = current->euid; - attr.ia_gid = current->egid; + attr.ia_uid = current->act_as->euid; + attr.ia_gid = current->act_as->egid;if (!new_valid_dev (dev))return -EINVAL ;
fs/smbfs/inode.c +1 -1
@@ -579,7 +579,7 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)if (parse_options (mnt, raw_data)) goto out_bad_option; } - mnt->mounted_uid = current->uid; + mnt->mounted_uid = current->act_as->uid;smb_setcodepage (server, &mnt->codepage);/*
fs/smbfs/proc.c +1 -1
@@ -865,7 +865,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt) goto out; error = -EACCES ; -if (current->uid != server->mnt->mounted_uid && +if (current->act_as->uid != server->mnt->mounted_uid && !capable (CAP_SYS_ADMIN )) goto out;
include/linux/init_task.h +17 -6
@@ -114,6 +114,20 @@ extern struct group_info init_groups; .pid = &init_struct_pid, \ } +extern struct task_security init_task_security; + +#define INIT_TASK_SECURITY (p) \ +{ \ + .usage = ATOMIC_INIT(3), \ + .keep_capabilities = 0, \ + .cap_inheritable = CAP_INIT_INH_SET, \ + .cap_permitted = CAP_FULL_SET, \ + .cap_effective = CAP_INIT_EFF_SET, \ + .user = INIT_USER, \ + .group_info = &init_groups, \ + .lock = __SPIN_LOCK_UNLOCKED(p.lock), \ +} +/* * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -143,12 +157,9 @@ extern struct group_info init_groups; .children = LIST_HEAD_INIT(tsk.children), \ .sibling = LIST_HEAD_INIT(tsk.sibling), \ .group_leader = &tsk, \ - .group_info = &init_groups, \ - .cap_effective = CAP_INIT_EFF_SET, \ - .cap_inheritable = CAP_INIT_INH_SET, \ - .cap_permitted = CAP_FULL_SET, \ - .keep_capabilities = 0, \ - .user = INIT_USER, \ + .__temp_sec = INIT_TASK_SECURITY(tsk.__temp_sec), \ + .sec = &tsk.__temp_sec, \ + .act_as = &tsk.__temp_sec, \ .comm = "swapper", \ .thread = INIT_THREAD, \ .fs = &init_fs, \
include/linux/sched.h +61 -17
102 lines not on this page · raw message
include/net/scm.h +2 -2
@@ -54,8 +54,8 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) {struct task_struct *p = current; - scm->creds.uid = p->uid; - scm->creds.gid = p->gid; + scm->creds.uid = p->sec->uid; + scm->creds.gid = p->sec->gid; scm->creds.pid =task_tgid_vnr (p); scm->fp =NULL ; scm->seq =0 ;
ipc/mqueue.c +2 -2
@@ -118,7 +118,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,if (S_ISREG (mode)) {struct mqueue_inode_info *info;struct task_struct *p = current; -struct user_struct *u = p->user; +struct user_struct *u = p->sec->user;unsigned long mq_bytes, mq_msg_tblsz; inode->i_fop = &mqueue_file_operations;
@@ -511,7 +511,7 @@ static void __do_notify(struct mqueue_inode_info *info) sig_i.si_code =SI_MESGQ ; sig_i.si_value = info->notify.sigev_value; sig_i.si_pid =task_pid_vnr (current); - sig_i.si_uid = current->uid; + sig_i.si_uid = current->act_as->uid;kill_pid_info (info->notify.sigev_signo, &sig_i, info->notify_owner);
ipc/msg.c +2 -2
@@ -551,8 +551,8 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) } err = -EPERM ; -if (current->euid != ipcp->cuid && - current->euid != ipcp->uid && !capable (CAP_SYS_ADMIN )) +if (current->act_as->euid != ipcp->cuid && + current->act_as->euid != ipcp->uid && !capable (CAP_SYS_ADMIN ))/* We _could_ check for CAP_CHOWN above, but we don't */ goto out_unlock_up;
ipc/sem.c +2 -2
@@ -924,8 +924,8 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,if (err) goto out_unlock; } -if (current->euid != ipcp->cuid && - current->euid != ipcp->uid && !capable (CAP_SYS_ADMIN )) { +if (current->act_as->euid != ipcp->cuid && + current->act_as->euid != ipcp->uid && !capable (CAP_SYS_ADMIN )) { err=-EPERM ; goto out_unlock; }
ipc/shm.c +8 -8
@@ -417,7 +417,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)if (shmflg &SHM_HUGETLB ) {/* hugetlb_file_setup takes care of mlock user accounting */ file =hugetlb_file_setup (name, size); - shp->mlock_user = current->user; + shp->mlock_user = current->sec->user; }else {int acctflag =VM_ACCOUNT ;/*
@@ -770,8 +770,8 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)if (!capable (CAP_IPC_LOCK )) { err = -EPERM ; -if (current->euid != shp->shm_perm.uid && - current->euid != shp->shm_perm.cuid) +if (current->act_as->euid != shp->shm_perm.uid && + current->act_as->euid != shp->shm_perm.cuid) goto out_unlock;if (cmd ==SHM_LOCK && !current->signal->rlim[RLIMIT_MEMLOCK ].rlim_cur)
@@ -783,7 +783,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) goto out_unlock;if (cmd==SHM_LOCK ) { -struct user_struct * user = current->user; +struct user_struct *user = current->act_as->user;if (!is_file_hugepages (shp->shm_file)) { err =shmem_lock (shp->shm_file,1 , user);if (!err && !(shp->shm_perm.mode &SHM_LOCKED )){
@@ -822,8 +822,8 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)if (err) goto out_unlock_up; -if (current->euid != shp->shm_perm.uid && - current->euid != shp->shm_perm.cuid && +if (current->act_as->euid != shp->shm_perm.uid && + current->act_as->euid != shp->shm_perm.cuid && !capable (CAP_SYS_ADMIN )) { err=-EPERM ; goto out_unlock_up;
@@ -862,8 +862,8 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)if (err) goto out_unlock_up; err=-EPERM ; -if (current->euid != shp->shm_perm.uid && - current->euid != shp->shm_perm.cuid && +if (current->act_as->euid != shp->shm_perm.uid && + current->act_as->euid != shp->shm_perm.cuid && !capable (CAP_SYS_ADMIN )) { goto out_unlock_up; }
ipc/util.c +4 -3
@@ -283,8 +283,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) ids->in_use++; - new->cuid = new->uid = current->euid; - new->gid = new->cgid = current->egid; + new->cuid = new->uid = current->act_as->euid; + new->gid = new->cgid = current->act_as->egid; new->seq = ids->seq++;if (ids->seq > ids->seq_max)
@@ -632,7 +632,8 @@ int ipcperms (struct kern_ipc_perm *ipcp, short flag)return err; requested_mode = (flag >>6 ) | (flag >>3 ) | flag; granted_mode = ipcp->mode; -if (current->euid == ipcp->cuid || current->euid == ipcp->uid) +if (current->act_as->euid == ipcp->cuid || + current->act_as->euid == ipcp->uid) granted_mode >>=6 ;else if (in_group_p (ipcp->cgid) ||in_group_p (ipcp->gid)) granted_mode >>=3 ;
kernel/acct.c +4 -4
@@ -470,15 +470,15 @@ static void do_acct_process(struct file *file)do_div (elapsed,AHZ ); ac.ac_btime =get_seconds () - elapsed;/* we really need to bite the bullet and change layout */ - ac.ac_uid = current->uid; - ac.ac_gid = current->gid; + ac.ac_uid = current->sec->uid; + ac.ac_gid = current->sec->gid;#if ACCT_VERSION ==2 ac.ac_ahz =AHZ ;#endif #if ACCT_VERSION ==1 ||ACCT_VERSION ==2 /* backward-compatible 16 bit fields */ - ac.ac_uid16 = current->uid; - ac.ac_gid16 = current->gid; + ac.ac_uid16 = current->sec->uid; + ac.ac_gid16 = current->sec->gid;#endif #if ACCT_VERSION ==3 ac.ac_pid = current->tgid;
kernel/auditsc.c +21 -19
@@ -394,6 +394,7 @@ static int audit_filter_rules(struct task_struct *tsk,struct audit_names *name, enum audit_state *state) { + struct task_security *sec = tsk->sec;int i, j, need_sid =1 ;u32 sid;
@@ -413,28 +414,28 @@ static int audit_filter_rules(struct task_struct *tsk, }break ;case AUDIT_UID : - result =audit_comparator (tsk->uid, f->op, f->val); + result =audit_comparator (sec->uid, f->op, f->val);break ;case AUDIT_EUID : - result =audit_comparator (tsk->euid, f->op, f->val); + result =audit_comparator (sec->euid, f->op, f->val);break ;case AUDIT_SUID : - result =audit_comparator (tsk->suid, f->op, f->val); + result =audit_comparator (sec->suid, f->op, f->val);break ;case AUDIT_FSUID : - result =audit_comparator (tsk->fsuid, f->op, f->val); + result =audit_comparator (sec->fsuid, f->op, f->val);break ;case AUDIT_GID : - result =audit_comparator (tsk->gid, f->op, f->val); + result =audit_comparator (sec->gid, f->op, f->val);break ;case AUDIT_EGID : - result =audit_comparator (tsk->egid, f->op, f->val); + result =audit_comparator (sec->egid, f->op, f->val);break ;case AUDIT_SGID : - result =audit_comparator (tsk->sgid, f->op, f->val); + result =audit_comparator (sec->sgid, f->op, f->val);break ;case AUDIT_FSGID : - result =audit_comparator (tsk->fsgid, f->op, f->val); + result =audit_comparator (sec->fsgid, f->op, f->val);break ;case AUDIT_PERS : result =audit_comparator (tsk->personality, f->op, f->val);
@@ -997,6 +998,7 @@ static void audit_log_execve_info(struct audit_buffer *ab,static void audit_log_exit (struct audit_context *context,struct task_struct *tsk) { +struct task_security *sec = tsk->sec;int i, call_panic =0 ;struct audit_buffer *ab;struct audit_aux_data *aux;
@@ -1006,14 +1008,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts context->pid = tsk->pid;if (!context->ppid) context->ppid =sys_getppid (); - context->uid = tsk->uid; - context->gid = tsk->gid; - context->euid = tsk->euid; - context->suid = tsk->suid; - context->fsuid = tsk->fsuid; - context->egid = tsk->egid; - context->sgid = tsk->sgid; - context->fsgid = tsk->fsgid; + context->uid = sec->uid; + context->gid = sec->gid; + context->euid = sec->euid; + context->suid = sec->suid; + context->fsuid = sec->fsuid; + context->egid = sec->egid; + context->sgid = sec->sgid; + context->fsgid = sec->fsgid; context->personality = tsk->personality; ab =audit_log_start (context,GFP_KERNEL ,AUDIT_SYSCALL );
@@ -1788,7 +1790,7 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)if (ab) {audit_log_format (ab,"login pid=%d uid=%u " "old auid=%u new auid=%u" , - task->pid, task->uid, + task->pid, task->sec->uid, context->loginuid, loginuid);audit_log_end (ab); }
@@ -2219,7 +2221,7 @@ int __audit_signal_info(int sig, struct task_struct *t)if (ctx) audit_sig_uid = ctx->loginuid;else - audit_sig_uid = tsk->uid; + audit_sig_uid = tsk->sec->uid;selinux_get_task_sid (tsk, &audit_sig_sid); }if (!audit_signals ||audit_dummy_context ())
@@ -2274,7 +2276,7 @@ void audit_core_dumps(long signr) ab =audit_log_start (NULL ,GFP_KERNEL ,AUDIT_ANOM_ABEND );audit_log_format (ab,"auid=%u uid=%u gid=%u" ,audit_get_loginuid (current->audit_context), - current->uid, current->gid); + current->sec->uid, current->sec->gid);selinux_get_task_sid (current, &sid);if (sid) {char *ctx =NULL ;
kernel/cgroup.c +3 -2
@@ -1247,8 +1247,9 @@ static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf)get_task_struct (tsk);rcu_read_unlock (); -if ((current->euid) && (current->euid != tsk->uid) - && (current->euid != tsk->suid)) { +if (current->act_as->euid && + current->act_as->euid != tsk->sec->uid && + current->act_as->euid != tsk->sec->suid) {put_task_struct (tsk);return -EACCES ; }
kernel/exit.c +6 -6
@@ -147,7 +147,7 @@ void release_task(struct task_struct * p)struct task_struct *leader;int zap_leader; repeat: -atomic_dec (&p->user->processes); +atomic_dec (&p->sec->user->processes);proc_flush_task (p);write_lock_irq (&tasklist_lock);ptrace_unlink (p);
@@ -1198,7 +1198,7 @@ static int wait_task_zombie(struct task_struct *p, int noreap,if (unlikely (noreap)) {pid_t pid =task_pid_nr_ns (p, ns); -uid_t uid = p->uid; +uid_t uid = p->sec->uid;int exit_code = p->exit_code;int why, status;
@@ -1318,7 +1318,7 @@ static int wait_task_zombie(struct task_struct *p, int noreap,if (!retval && infop) retval =put_user (task_pid_nr_ns (p, ns), &infop->si_pid);if (!retval && infop) - retval =put_user (p->uid, &infop->si_uid); + retval =put_user (p->sec->uid, &infop->si_uid);if (!retval) retval =task_pid_nr_ns (p, ns);
@@ -1381,7 +1381,7 @@ static int wait_task_stopped(struct task_struct *p, int delayed_group_leader,read_unlock (&tasklist_lock);if (unlikely (noreap)) { -uid_t uid = p->uid; +uid_t uid = p->sec->uid;int why = (p->ptrace &PT_PTRACED ) ?CLD_TRAPPED :CLD_STOPPED ; exit_code = p->exit_code;
@@ -1452,7 +1452,7 @@ bail_ref:if (!retval && infop) retval =put_user (pid, &infop->si_pid);if (!retval && infop) - retval =put_user (p->uid, &infop->si_uid); + retval =put_user (p->sec->uid, &infop->si_uid);if (!retval) retval = pid;put_task_struct (p);
@@ -1491,7 +1491,7 @@ static int wait_task_continued(struct task_struct *p, int noreap, ns = current->nsproxy->pid_ns; pid =task_pid_nr_ns (p, ns); - uid = p->uid; + uid = p->sec->uid;get_task_struct (p);read_unlock (&tasklist_lock);
kernel/fork.c +12 -11
@@ -122,8 +122,8 @@ void __put_task_struct(struct task_struct *tsk)WARN_ON (tsk == current);security_task_free (tsk); -free_uid (tsk->user); -put_group_info (tsk->group_info); +free_uid (tsk->__temp_sec.user); +put_group_info (tsk->__temp_sec.group_info);delayacct_tsk_free (tsk);if (!profile_handoff_task (tsk))
@@ -1014,17 +1014,18 @@ static struct task_struct *copy_process(unsigned long clone_flags,DEBUG_LOCKS_WARN_ON (!p->hardirqs_enabled);DEBUG_LOCKS_WARN_ON (!p->softirqs_enabled);#endif + p->act_as = p->sec = &p->__temp_sec; retval = -EAGAIN ; -if (atomic_read (&p->user->processes) >= +if (atomic_read (&p->sec->user->processes) >= p->signal->rlim[RLIMIT_NPROC ].rlim_cur) {if (!capable (CAP_SYS_ADMIN ) && !capable (CAP_SYS_RESOURCE ) && - p->user != current->nsproxy->user_ns->root_user) + p->sec->user != current->nsproxy->user_ns->root_user) goto bad_fork_free; } -atomic_inc (&p->user->__count); -atomic_inc (&p->user->processes); -get_group_info (p->group_info); +atomic_inc (&p->sec->user->__count); +atomic_inc (&p->sec->user->processes); +get_group_info (p->sec->group_info);/* * If multiple threads are within copy_process(), then this check
@@ -1080,7 +1081,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->real_start_time = p->start_time;monotonic_to_bootbased (&p->real_start_time);#ifdef CONFIG_SECURITY - p->security =NULL ; + p->sec->security =NULL ;#endif p->io_context =NULL ; p->audit_context =NULL ;
@@ -1350,9 +1351,9 @@ bad_fork_cleanup_cgroup: bad_fork_cleanup_put_domain:module_put (task_thread_info (p)->exec_domain->module); bad_fork_cleanup_count: -put_group_info (p->group_info); -atomic_dec (&p->user->processes); -free_uid (p->user); +put_group_info (p->sec->group_info); +atomic_dec (&p->sec->user->processes); +free_uid (p->sec->user); bad_fork_free:free_task (p); fork_out:
kernel/futex.c +5 -3
@@ -444,7 +444,8 @@ static struct task_struct * futex_find_get_task(pid_t pid)rcu_read_lock (); p =find_task_by_vpid (pid); -if (!p || ((current->euid != p->euid) && (current->euid != p->uid))) +if (!p || (current->act_as->euid != p->sec->euid && + current->act_as->euid != p->sec->uid)) p =ERR_PTR (-ESRCH );else get_task_struct (p);
@@ -1889,8 +1890,9 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,if (!p) goto err_unlock; ret = -EPERM ; -if ((current->euid != p->euid) && (current->euid != p->uid) && - !capable (CAP_SYS_PTRACE )) +if (current->act_as->euid != p->sec->euid && + current->act_as->euid != p->sec->uid && + !capable (CAP_SYS_PTRACE )) goto err_unlock; head = p->robust_list;rcu_read_unlock ();
kernel/futex_compat.c +3 -2
@@ -141,8 +141,9 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,if (!p) goto err_unlock; ret = -EPERM ; -if ((current->euid != p->euid) && (current->euid != p->uid) && - !capable (CAP_SYS_PTRACE )) +if (current->act_as->euid != p->sec->euid && + current->act_as->euid != p->sec->uid && + !capable (CAP_SYS_PTRACE )) goto err_unlock; head = p->compat_robust_list;read_unlock (&tasklist_lock);
kernel/ptrace.c +8 -6
@@ -122,6 +122,8 @@ int ptrace_check_attach(struct task_struct *child, int kill)int __ptrace_may_attach (struct task_struct *task) { +struct task_security *sec = current->act_as, *tsec = task->sec; +/* May we inspect the given task? * This check is used both for attaching with ptrace * and for allowing access to sensitive information in /proc.
@@ -134,12 +136,12 @@ int __ptrace_may_attach(struct task_struct *task)/* Don't let security modules deny introspection */ if (task == current)return 0 ; -if (((current->uid != task->euid) || - (current->uid != task->suid) || - (current->uid != task->uid) || - (current->gid != task->egid) || - (current->gid != task->sgid) || - (current->gid != task->gid)) && !capable (CAP_SYS_PTRACE )) +if (((sec->uid != tsec->euid) || + (sec->uid != tsec->suid) || + (sec->uid != tsec->uid) || + (sec->gid != tsec->egid) || + (sec->gid != tsec->sgid) || + (sec->gid != tsec->gid)) && !capable (CAP_SYS_PTRACE ))return -EPERM ;smp_rmb ();if (task->mm)
kernel/sched.c +5 -4
@@ -4311,8 +4311,8 @@ recheck:return -EPERM ;/* can't change other user's priorities */ -if ((current->euid != p->euid) && - (current->euid != p->uid)) +if ((current->act_as->euid != p->sec->euid) && + (current->act_as->euid != p->sec->uid))return -EPERM ; }
@@ -4509,8 +4509,9 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask)read_unlock (&tasklist_lock); retval = -EPERM ; -if ((current->euid != p->euid) && (current->euid != p->uid) && - !capable (CAP_SYS_NICE )) +if ((current->act_as->euid != p->sec->euid) && + (current->act_as->euid != p->sec->uid) && + !capable (CAP_SYS_NICE )) goto out_unlock; retval =security_task_setscheduler (p,0 ,NULL );
kernel/signal.c +14 -12
@@ -174,7 +174,7 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,* In order to avoid problems with "switch_user()", we want to make * sure that the compiler doesn't re-load "t->user" */ - user = t->user; + user = t->sec->user;barrier ();atomic_inc (&user->sigpending); if (override_rlimit ||
@@ -537,8 +537,10 @@ static int check_kill_permission(int sig, struct siginfo *info, error = -EPERM ;if (((sig !=SIGCONT ) || (task_session_nr (current) !=task_session_nr (t))) - && (current->euid ^ t->suid) && (current->euid ^ t->uid) - && (current->uid ^ t->suid) && (current->uid ^ t->uid) + && (current->act_as->euid ^ t->sec->suid) + && (current->act_as->euid ^ t->sec->uid) + && (current->act_as->uid ^ t->sec->suid) + && (current->act_as->uid ^ t->sec->uid) && !capable (CAP_KILL ))return error; }
@@ -695,7 +697,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, q->info.si_errno =0 ; q->info.si_code =SI_USER ; q->info.si_pid =task_pid_vnr (current); - q->info.si_uid = current->uid; + q->info.si_uid = current->act_as->uid;break ;case (unsigned long )SEND_SIG_PRIV : q->info.si_signo = sig;
@@ -1111,8 +1113,8 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid, goto out_unlock; }if ((info ==SEND_SIG_NOINFO || (!is_si_special (info) &&SI_FROMUSER (info))) - && (euid != p->suid) && (euid != p->uid) - && (uid != p->suid) && (uid != p->uid)) { + && (euid != p->sec->suid) && (euid != p->sec->uid) + && (uid != p->sec->suid) && (uid != p->sec->uid)) { ret = -EPERM ; goto out_unlock; }
@@ -1464,7 +1466,7 @@ void do_notify_parent(struct task_struct *tsk, int sig) info.si_pid =task_pid_nr_ns (tsk, tsk->parent->nsproxy->pid_ns);rcu_read_unlock (); - info.si_uid = tsk->uid; + info.si_uid = tsk->sec->uid;/* FIXME: find out whether or not this is supposed to be c*time. */ info.si_utime = cputime_to_jiffies(cputime_add(tsk->utime,
@@ -1535,7 +1537,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why) info.si_pid =task_pid_nr_ns (tsk, tsk->parent->nsproxy->pid_ns);rcu_read_unlock (); - info.si_uid = tsk->uid; + info.si_uid = tsk->sec->uid;/* FIXME: find out whether or not this is supposed to be c*time. */ info.si_utime =cputime_to_jiffies (tsk->utime);
@@ -1661,7 +1663,7 @@ void ptrace_notify(int exit_code) info.si_signo =SIGTRAP ; info.si_code = exit_code; info.si_pid =task_pid_vnr (current); - info.si_uid = current->uid; + info.si_uid = current->sec->uid;/* Let the debugger run. */ spin_lock_irq (¤t->sighand->siglock);
@@ -1831,7 +1833,7 @@ relock: info->si_errno =0 ; info->si_code =SI_USER ; info->si_pid =task_pid_vnr (current->parent); - info->si_uid = current->parent->uid; + info->si_uid = current->parent->sec->uid; }/* If the (new) signal is now blocked, requeue it. */
@@ -2218,7 +2220,7 @@ sys_kill(int pid, int sig) info.si_errno =0 ; info.si_code =SI_USER ; info.si_pid =task_tgid_vnr (current); - info.si_uid = current->uid; + info.si_uid = current->act_as->uid;return kill_something_info (sig, &info, pid); }
@@ -2234,7 +2236,7 @@ static int do_tkill(int tgid, int pid, int sig) info.si_errno =0 ; info.si_code =SI_TKILL ; info.si_pid =task_tgid_vnr (current); - info.si_uid = current->uid; + info.si_uid = current->act_as->uid;read_lock (&tasklist_lock); p =find_task_by_vpid (pid);
kernel/sys.c +132 -119
581 lines not on this page · raw message
kernel/sysctl.c +1 -1
@@ -1382,7 +1382,7 @@ out:static int test_perm (int mode,int op) { -if (!current->euid) +if (!current->act_as->euid) mode >>=6 ;else if (in_egroup_p (0 )) mode >>=3 ;
kernel/timer.c +4 -4
@@ -987,25 +987,25 @@ asmlinkage long sys_getppid(void)asmlinkage long sys_getuid (void ) {/* Only we change this so SMP safe */ -return current->uid; +return current->sec->uid; }asmlinkage long sys_geteuid (void ) {/* Only we change this so SMP safe */ -return current->euid; +return current->sec->euid; }asmlinkage long sys_getgid (void ) {/* Only we change this so SMP safe */ -return current->gid; +return current->sec->gid; }asmlinkage long sys_getegid (void ) {/* Only we change this so SMP safe */ -return current->egid; +return current->sec->egid; }#endif
kernel/uid16.c +14 -14
@@ -86,9 +86,9 @@ asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid, {int retval; -if (!(retval =put_user (high2lowuid (current->uid), ruid)) && - !(retval =put_user (high2lowuid (current->euid), euid))) - retval =put_user (high2lowuid (current->suid), suid); +if (!(retval =put_user (high2lowuid (current->sec->uid), ruid)) && + !(retval =put_user (high2lowuid (current->sec->euid), euid))) + retval =put_user (high2lowuid (current->sec->suid), suid);return retval; }
@@ -106,9 +106,9 @@ asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid, {int retval; -if (!(retval =put_user (high2lowgid (current->gid), rgid)) && - !(retval =put_user (high2lowgid (current->egid), egid))) - retval =put_user (high2lowgid (current->sgid), sgid); +if (!(retval =put_user (high2lowgid (current->sec->gid), rgid)) && + !(retval =put_user (high2lowgid (current->sec->egid), egid))) + retval =put_user (high2lowgid (current->sec->sgid), sgid);return retval; }
@@ -166,20 +166,20 @@ asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist)if (gidsetsize <0 )return -EINVAL ; -get_group_info (current->group_info); - i = current->group_info->ngroups; +get_group_info (current->sec->group_info); + i = current->sec->group_info->ngroups;if (gidsetsize) {if (i > gidsetsize) { i = -EINVAL ; goto out; } -if (groups16_to_user (grouplist, current->group_info)) { +if (groups16_to_user (grouplist, current->sec->group_info)) { i = -EFAULT ; goto out; } } out: -put_group_info (current->group_info); +put_group_info (current->sec->group_info);return i; }
@@ -210,20 +210,20 @@ asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist)asmlinkage long sys_getuid16 (void ) { -return high2lowuid (current->uid); +return high2lowuid (current->sec->uid); }asmlinkage long sys_geteuid16 (void ) { -return high2lowuid (current->euid); +return high2lowuid (current->sec->euid); }asmlinkage long sys_getgid16 (void ) { -return high2lowgid (current->gid); +return high2lowgid (current->sec->gid); }asmlinkage long sys_getegid16 (void ) { -return high2lowgid (current->egid); +return high2lowgid (current->sec->egid); }
kernel/user.c +2 -2
@@ -416,11 +416,11 @@ void switch_uid(struct user_struct *new_user)* cheaply with the new uid cache, so if it matters * we should be checking for it. -DaveM */ - old_user = current->user; + old_user = current->sec->user;atomic_inc (&new_user->processes);atomic_dec (&old_user->processes);switch_uid_keyring (new_user); - current->user = new_user; + current->sec->user = new_user;sched_switch_user (current);/*
kernel/user_namespace.c +1 -1
@@ -49,7 +49,7 @@ static struct user_namespace *clone_user_ns(struct user_namespace *old_ns) }/* Reset current->user with a new one */ - new_user =alloc_uid (ns, current->uid); + new_user =alloc_uid (ns, current->sec->uid);if (!new_user) {free_uid (ns->root_user);kfree (ns);
mm/oom_kill.c +3 -3
@@ -125,8 +125,8 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)* Superuser processes are usually more important, so we make it * less likely that we kill those. */ -if (cap_t (p->cap_effective) &CAP_TO_MASK (CAP_SYS_ADMIN ) || - p->uid ==0 || p->euid ==0 ) +if (cap_t (p->sec->cap_effective) &CAP_TO_MASK (CAP_SYS_ADMIN ) || + p->sec->uid ==0 || p->sec->euid ==0 ) points /=4 ;/*
@@ -135,7 +135,7 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)* tend to only have this flag set on applications they think * of as important. */ -if (cap_t (p->cap_effective) &CAP_TO_MASK (CAP_SYS_RAWIO )) +if (cap_t (p->sec->cap_effective) &CAP_TO_MASK (CAP_SYS_RAWIO )) points /=4 ;/*
net/core/scm.c +6 -4
@@ -44,11 +44,13 @@static __inline__int scm_check_creds (struct ucred *creds) { +struct task_security *sec = current->act_as; +if ((creds->pid ==task_tgid_vnr (current) ||capable (CAP_SYS_ADMIN )) && - ((creds->uid == current->uid || creds->uid == current->euid || - creds->uid == current->suid) ||capable (CAP_SETUID )) && - ((creds->gid == current->gid || creds->gid == current->egid || - creds->gid == current->sgid) ||capable (CAP_SETGID ))) { + ((creds->uid == sec->uid || creds->uid == sec->euid || + creds->uid == sec->suid) ||capable (CAP_SETUID )) && + ((creds->gid == sec->gid || creds->gid == sec->egid || + creds->gid == sec->sgid) ||capable (CAP_SETGID ))) {return 0 ; }return -EPERM ;
net/sunrpc/auth.c +2 -2
@@ -339,7 +339,7 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags)struct auth_cred acred = { .uid =current_fsuid (), .gid =current_fsgid (), - .group_info = current->group_info, + .group_info = current->act_as->group_info, };struct rpc_cred *ret;
@@ -375,7 +375,7 @@ rpcauth_bindcred(struct rpc_task *task)struct auth_cred acred = { .uid =current_fsuid (), .gid =current_fsgid (), - .group_info = current->group_info, + .group_info = current->act_as->group_info, };struct rpc_cred *ret;int flags =0 ;
net/unix/af_unix.c +6 -6
@@ -484,8 +484,8 @@ static int unix_listen(struct socket *sock, int backlog) sk->sk_state =TCP_LISTEN ;/* set credentials so connect can copy them */ sk->sk_peercred.pid =task_tgid_vnr (current); - sk->sk_peercred.uid = current->euid; - sk->sk_peercred.gid = current->egid; + sk->sk_peercred.uid = current->act_as->euid; + sk->sk_peercred.gid = current->act_as->egid; err =0 ; out_unlock:
@@ -1135,8 +1135,8 @@ restart: newsk->sk_state =TCP_ESTABLISHED ; newsk->sk_type = sk->sk_type; newsk->sk_peercred.pid =task_tgid_vnr (current); - newsk->sk_peercred.uid = current->euid; - newsk->sk_peercred.gid = current->egid; + newsk->sk_peercred.uid = current->act_as->euid; + newsk->sk_peercred.gid = current->act_as->egid; newu =unix_sk (newsk); newsk->sk_sleep = &newu->peer_wait; otheru =unix_sk (other);
@@ -1196,8 +1196,8 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb)unix_peer (ska)=skb;unix_peer (skb)=ska; ska->sk_peercred.pid = skb->sk_peercred.pid =task_tgid_vnr (current); - ska->sk_peercred.uid = skb->sk_peercred.uid = current->euid; - ska->sk_peercred.gid = skb->sk_peercred.gid = current->egid; + ska->sk_peercred.uid = skb->sk_peercred.uid = current->act_as->euid; + ska->sk_peercred.gid = skb->sk_peercred.gid = current->act_as->egid;if (ska->sk_type !=SOCK_DGRAM ) { ska->sk_state =TCP_ESTABLISHED ;
security/commoncap.c +63 -47
237 lines not on this page · raw message
security/dummy.c +25 -15
@@ -37,11 +37,11 @@ static int dummy_capget (struct task_struct *target, kernel_cap_t * effective, kernel_cap_t * inheritable, kernel_cap_t * permitted) { *effective = *inheritable = *permitted =0 ; -if (target->euid ==0 ) { +if (target->sec->euid ==0 ) { *permitted |= (~0 & ~CAP_FS_MASK ); *effective |= (~0 & ~CAP_TO_MASK (CAP_SETPCAP ) & ~CAP_FS_MASK ); } -if (target->fsuid ==0 ) { +if (target->sec->fsuid ==0 ) { *permitted |=CAP_FS_MASK ; *effective |=CAP_FS_MASK ; }
@@ -71,7 +71,7 @@ static int dummy_acct (struct file *file)static int dummy_capable (struct task_struct *tsk,int cap) { -if (cap_raised (tsk->cap_effective, cap)) +if (cap_raised (tsk->act_as->cap_effective, cap))return 0 ;return -EPERM ; }
@@ -93,7 +93,7 @@ static int dummy_quota_on (struct dentry *dentry)static int dummy_syslog (int type) { -if ((type !=3 && type !=10 ) && current->euid) +if ((type !=3 && type !=10 ) && current->act_as->euid)return -EPERM ;return 0 ; }
@@ -126,19 +126,24 @@ static void dummy_bprm_free_security (struct linux_binprm *bprm)static void dummy_bprm_apply_creds (struct linux_binprm *bprm,int unsafe) { -if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) { +struct task_security *sec = current->sec; + +if (bprm->e_uid != sec->uid || bprm->e_gid != sec->gid) {set_dumpable (current->mm, suid_dumpable);if ((unsafe & ~LSM_UNSAFE_PTRACE_CAP ) && !capable (CAP_SETUID )) { - bprm->e_uid = current->uid; - bprm->e_gid = current->gid; + bprm->e_uid = sec->uid; + bprm->e_gid = sec->gid; } } - current->suid = current->euid = current->fsuid = bprm->e_uid; - current->sgid = current->egid = current->fsgid = bprm->e_gid; + sec->suid = sec->euid = sec->fsuid = bprm->e_uid; + sec->sgid = sec->egid = sec->fsgid = bprm->e_gid; -dummy_capget (current, ¤t->cap_effective, ¤t->cap_inheritable, ¤t->cap_permitted); +dummy_capget (current, + &sec->cap_effective, + &sec->cap_inheritable, + &sec->cap_permitted); }static void dummy_bprm_post_apply_creds (struct linux_binprm *bprm)
@@ -162,8 +167,8 @@ static int dummy_bprm_secureexec (struct linux_binprm *bprm)in the AT_SECURE field to decide whether secure mode is required. Hence, this logic is required to preserve the legacy decision algorithm used by the old userland. */ -return (current->euid != current->uid || - current->egid != current->gid); +return (current->sec->euid != current->sec->uid || + current->sec->egid != current->sec->gid); }static int dummy_sb_alloc_security (struct super_block *sb)
@@ -492,7 +497,12 @@ static int dummy_task_setuid (uid_t id0, uid_t id1, uid_t id2, int flags)static int dummy_task_post_setuid (uid_t id0,uid_t id1,uid_t id2,int flags) { -dummy_capget (current, ¤t->cap_effective, ¤t->cap_inheritable, ¤t->cap_permitted); +struct task_security *sec = current->sec; + +dummy_capget (current, + &sec->cap_effective, + &sec->cap_inheritable, + &sec->cap_permitted);return 0 ; }
@@ -579,7 +589,7 @@ static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3,static void dummy_task_reparent_to_init (struct task_struct *p) { - p->euid = p->fsuid =0 ; + p->sec->euid = p->sec->fsuid =0 ;return ; }
@@ -689,7 +699,7 @@ static int dummy_sem_semop (struct sem_array *sma,static int dummy_netlink_send (struct sock *sk,struct sk_buff *skb) { -NETLINK_CB (skb).eff_cap = current->cap_effective; +NETLINK_CB (skb).eff_cap = current->act_as->cap_effective;return 0 ; }
security/keys/key.c +1 -1
@@ -817,7 +817,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, perm |=KEY_USR_WRITE ;/* allocate a new key */ - key =key_alloc (ktype, description,current_fsuid (), current->fsgid, + key =key_alloc (ktype, description,current_fsuid (),current_fsgid (), current, perm, flags);if (IS_ERR (key)) { key_ref =ERR_PTR (PTR_ERR (key));
security/keys/keyctl.c +13 -12
@@ -846,7 +846,7 @@ long keyctl_instantiate_key(key_serial_t id,/* the appropriate instantiation authorisation key must have been * assumed before calling this */ ret = -EPERM ; - instkey = current->request_key_auth; + instkey = current->sec->request_key_auth;if (!instkey) goto error;
@@ -895,8 +895,8 @@ long keyctl_instantiate_key(key_serial_t id,/* discard the assumed authority if it's just been disabled by * instantiation of the key */ if (ret ==0 ) { -key_put (current->request_key_auth); - current->request_key_auth =NULL ; +key_put (current->sec->request_key_auth); + current->sec->request_key_auth =NULL ; } error2:
@@ -924,7 +924,7 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)/* the appropriate instantiation authorisation key must have been * assumed before calling this */ ret = -EPERM ; - instkey = current->request_key_auth; + instkey = current->sec->request_key_auth;if (!instkey) goto error;
@@ -952,8 +952,8 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)/* discard the assumed authority if it's just been disabled by * instantiation of the key */ if (ret ==0 ) { -key_put (current->request_key_auth); - current->request_key_auth =NULL ; +key_put (current->sec->request_key_auth); + current->sec->request_key_auth =NULL ; } error:
@@ -968,6 +968,7 @@ error:*/ long keyctl_set_reqkey_keyring (int reqkey_defl) { +struct task_security *sec = current->sec;int ret;switch (reqkey_defl) {
@@ -987,10 +988,10 @@ long keyctl_set_reqkey_keyring(int reqkey_defl)case KEY_REQKEY_DEFL_USER_KEYRING :case KEY_REQKEY_DEFL_USER_SESSION_KEYRING : set: - current->jit_keyring = reqkey_defl; + sec->jit_keyring = reqkey_defl;case KEY_REQKEY_DEFL_NO_CHANGE : -return current->jit_keyring; +return sec->jit_keyring;case KEY_REQKEY_DEFL_GROUP_KEYRING :default :
@@ -1055,8 +1056,8 @@ long keyctl_assume_authority(key_serial_t id)/* we divest ourselves of authority if given an ID of 0 */ if (id ==0 ) { -key_put (current->request_key_auth); - current->request_key_auth =NULL ; +key_put (current->sec->request_key_auth); + current->sec->request_key_auth =NULL ; ret =0 ; goto error; }
@@ -1072,8 +1073,8 @@ long keyctl_assume_authority(key_serial_t id) goto error; } -key_put (current->request_key_auth); - current->request_key_auth = authkey; +key_put (current->sec->request_key_auth); + current->sec->request_key_auth = authkey; ret = authkey->serial; error:
security/keys/permission.c +6 -5
@@ -22,6 +22,7 @@ int key_task_permission(const key_ref_t key_ref, struct task_struct *context, key_perm_t perm) { +struct task_security *sec = context->act_as;struct key *key;key_perm_t kperm;int ret;
@@ -29,7 +30,7 @@ int key_task_permission(const key_ref_t key_ref, key =key_ref_to_ptr (key_ref);/* use the second 8-bits of permissions for keys the caller owns */ -if (key->uid == context->fsuid) { +if (key->uid == sec->fsuid) { kperm = key->perm >>16 ; goto use_these_perms; }
@@ -37,14 +38,14 @@ int key_task_permission(const key_ref_t key_ref,/* use the third 8-bits of permissions for keys the caller has a group * membership in common with */ if (key->gid !=-1 && key->perm &KEY_GRP_ALL ) { -if (key->gid == context->fsgid) { +if (key->gid == sec->fsgid) { kperm = key->perm >>8 ; goto use_these_perms; } -task_lock (context); - ret =groups_search (context->group_info, key->gid); -task_unlock (context); +spin_lock (&sec->lock); + ret =groups_search (sec->group_info, key->gid); +spin_unlock (&sec->lock);if (ret) { kperm = key->perm >>8 ;
security/keys/process_keys.c +39 -37
209 lines not on this page · raw message
security/keys/request_key.c +9 -8
@@ -76,7 +76,7 @@ static int call_sbin_request_key(struct key_construction *cons,/* allocate a new session keyring */ sprintf (desc,"_req.%u" , key->serial); - keyring =keyring_alloc (desc,current_fsuid (), current->fsgid, current, + keyring =keyring_alloc (desc,current_fsuid (),current_fsgid (), current,KEY_ALLOC_QUOTA_OVERRUN ,NULL );if (IS_ERR (keyring)) { ret =PTR_ERR (keyring);
@@ -97,7 +97,8 @@ static int call_sbin_request_key(struct key_construction *cons,/* we specify the process's default keyrings */ sprintf (keyring_str[0 ],"%d" , - tsk->thread_keyring ? tsk->thread_keyring->serial :0 ); + tsk->act_as->thread_keyring ? + tsk->act_as->thread_keyring->serial :0 ); prkey =0 ;if (tsk->signal->process_keyring)
@@ -110,7 +111,7 @@ static int call_sbin_request_key(struct key_construction *cons, sskey =rcu_dereference (tsk->signal->session_keyring)->serial;rcu_read_unlock (); }else { - sskey = tsk->user->session_keyring->serial; + sskey = tsk->act_as->user->session_keyring->serial; }sprintf (keyring_str[2 ],"%d" , sskey);
@@ -216,10 +217,10 @@ static void construct_key_make_link(struct key *key, struct key *dest_keyring)/* find the appropriate keyring */ if (!dest_keyring) { -switch (tsk->jit_keyring) { +switch (tsk->act_as->jit_keyring) {case KEY_REQKEY_DEFL_DEFAULT :case KEY_REQKEY_DEFL_THREAD_KEYRING : - dest_keyring = tsk->thread_keyring; + dest_keyring = tsk->act_as->thread_keyring;if (dest_keyring)break ;
@@ -239,11 +240,11 @@ static void construct_key_make_link(struct key *key, struct key *dest_keyring)break ;case KEY_REQKEY_DEFL_USER_SESSION_KEYRING : - dest_keyring = tsk->user->session_keyring; + dest_keyring = tsk->act_as->user->session_keyring;break ;case KEY_REQKEY_DEFL_USER_KEYRING : - dest_keyring = tsk->user->uid_keyring; + dest_keyring = tsk->act_as->user->uid_keyring;break ;case KEY_REQKEY_DEFL_GROUP_KEYRING :
@@ -278,7 +279,7 @@ static int construct_alloc_key(struct key_type *type,mutex_lock (&user->cons_lock); key =key_alloc (type, description, -current_fsuid (), current->fsgid, current,KEY_POS_ALL , +current_fsuid (),current_fsgid (), current,KEY_POS_ALL , flags);if (IS_ERR (key)) goto alloc_failed;
security/keys/request_key_auth.c +7 -7
@@ -162,22 +162,22 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,/* see if the calling process is already servicing the key request of * another process */ -if (current->request_key_auth) { +if (current->act_as->request_key_auth) {/* it is - use that instantiation context here too */ -down_read (¤t->request_key_auth->sem); +down_read (¤t->act_as->request_key_auth->sem);/* if the auth key has been revoked, then the key we're * servicing is already instantiated */ if (test_bit (KEY_FLAG_REVOKED , - ¤t->request_key_auth->flags)) + ¤t->act_as->request_key_auth->flags)) goto auth_key_revoked; - irka = current->request_key_auth->payload.data; + irka = current->act_as->request_key_auth->payload.data; rka->context = irka->context; rka->pid = irka->pid;get_task_struct (rka->context); -up_read (¤t->request_key_auth->sem); +up_read (¤t->act_as->request_key_auth->sem); }else {/* it isn't - use this process as the context */
@@ -194,7 +194,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,sprintf (desc,"%x" , target->serial); authkey =key_alloc (&key_type_request_key_auth, desc, -current_fsuid (), current->fsgid, current, +current_fsuid (),current_fsgid (), current,KEY_POS_VIEW |KEY_POS_READ |KEY_POS_SEARCH |KEY_USR_VIEW ,KEY_ALLOC_NOT_IN_QUOTA );if (IS_ERR (authkey)) {
@@ -211,7 +211,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,return authkey; auth_key_revoked: -up_read (¤t->request_key_auth->sem); +up_read (¤t->act_as->request_key_auth->sem);kfree (rka->callout_info);kfree (rka);kleave ("= -EKEYREVOKED" );
security/selinux/exports.c +2 -2
@@ -56,7 +56,7 @@ void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)void selinux_get_task_sid (struct task_struct *tsk,u32 *sid) {if (selinux_enabled) { -struct task_security_struct *tsec = tsk->security; +struct task_security_struct *tsec = tsk->sec->security; *sid = tsec->sid;return ; }
@@ -77,7 +77,7 @@ EXPORT_SYMBOL_GPL(selinux_string_to_sid);int selinux_relabel_packet_permission (u32 sid) {if (selinux_enabled) { -struct task_security_struct *tsec = current->security; +struct task_security_struct *tsec = current->act_as->security;return avc_has_perm (tsec->sid, sid,SECCLASS_PACKET ,PACKET__RELABELTO ,NULL );
security/selinux/hooks.c +56 -55
86 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
David Howells
maintainerPATCH 1/1 Extra task_struct -> task_security separation
Extra bits for separation of task_struct -> task_security to make allyesconfig compile for i386 and x86_64. This will be rolled into patch 06 of 12.
From: David Howells <[email protected]>
---
drivers/connector/cn_proc.c | 8 ++++---- drivers/media/video/cpia.c | 2 +- drivers/net/tun.c | 4 ++-- drivers/net/wan/sbni.c | 8 ++++---- drivers/usb/core/devio.c | 8 ++++---- fs/dquot.c | 3 ++- kernel/sched.c | 2 +- kernel/tsacct.c | 4 ++-- mm/mempolicy.c | 7 +++++-- mm/migrate.c | 7 +++++-- net/ax25/af_ax25.c | 2 +- net/ax25/ax25_route.c | 2 +- net/ipv6/ip6_flowlabel.c | 2 +- net/netrom/af_netrom.c | 4 ++-- net/rose/af_rose.c | 4 ++-- security/commoncap.c | 7 ++++--- security/selinux/xfrm.c | 6 +++--- 17 files changed, 44 insertions(+), 36 deletions(-)
drivers/connector/cn_proc.c +4 -4
@@ -116,11 +116,11 @@ void proc_id_connector(struct task_struct *task, int which_id) ev->event_data.id.process_pid = task->pid; ev->event_data.id.process_tgid = task->tgid;if (which_id ==PROC_EVENT_UID ) { - ev->event_data.id.r.ruid = task->uid; - ev->event_data.id.e.euid = task->euid; + ev->event_data.id.r.ruid = task->act_as->uid; + ev->event_data.id.e.euid = task->act_as->euid; }else if (which_id ==PROC_EVENT_GID ) { - ev->event_data.id.r.rgid = task->gid; - ev->event_data.id.e.egid = task->egid; + ev->event_data.id.r.rgid = task->act_as->gid; + ev->event_data.id.e.egid = task->act_as->egid; }else return ;get_seq (&msg->seq, &ev->cpu);
drivers/media/video/cpia.c +1 -1
@@ -3202,7 +3202,7 @@ static int cpia_open(struct inode *inode, struct file *file)/* Set ownership of /proc/cpia/videoX to current user */ if (cam->proc_entry) - cam->proc_entry->uid = current->uid; + cam->proc_entry->uid = current->act_as->uid;/* set mark for loading first frame uncompressed */ cam->first_frame =1 ;
drivers/net/tun.c +2 -2
@@ -474,9 +474,9 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)/* Check permissions */ if (((tun->owner !=-1 && - current->euid != tun->owner) || + current->act_as->euid != tun->owner) || (tun->group !=-1 && - current->egid != tun->group)) && + current->act_as->egid != tun->group)) && !capable (CAP_NET_ADMIN ))return -EPERM ; }
drivers/net/wan/sbni.c +4 -4
@@ -1317,7 +1317,7 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd )break ;case SIOCDEVRESINSTATS : -if ( current->euid !=0 )/* root only */ +if (current->act_as->euid !=0 )/* root only */ return -EPERM ;memset ( &nl->in_stats,0 ,sizeof (struct sbni_in_stats ) );break ;
@@ -1334,7 +1334,7 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd )break ;case SIOCDEVSHWSTATE : -if ( current->euid !=0 )/* root only */ +if (current->act_as->euid !=0 )/* root only */ return -EPERM ;spin_lock ( &nl->lock );
@@ -1355,7 +1355,7 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd )#ifdef CONFIG_SBNI_MULTILINE case SIOCDEVENSLAVE : -if ( current->euid !=0 )/* root only */ +if (current->act_as->euid !=0 )/* root only */ return -EPERM ;if (copy_from_user ( slave_name, ifr->ifr_data,sizeof slave_name ))
@@ -1370,7 +1370,7 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd )return enslave ( dev, slave_dev );case SIOCDEVEMANSIPATE : -if ( current->euid !=0 )/* root only */ +if (current->act_as->euid !=0 )/* root only */ return -EPERM ;return emancipate ( dev );
drivers/usb/core/devio.c +4 -4
@@ -575,8 +575,8 @@ static int usbdev_open(struct inode *inode, struct file *file)init_waitqueue_head (&ps->wait); ps->discsignr =0 ; ps->disc_pid =get_pid (task_pid (current)); - ps->disc_uid = current->uid; - ps->disc_euid = current->euid; + ps->disc_uid = current->sec->uid; + ps->disc_euid = current->sec->euid; ps->disccontext =NULL ; ps->ifclaimed =0 ;security_task_getsecid (current, &ps->secid);
@@ -1082,8 +1082,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, as->signr = uurb->signr; as->ifnum = ifnum; as->pid =get_pid (task_pid (current)); - as->uid = current->uid; - as->euid = current->euid; + as->uid = current->sec->uid; + as->euid = current->sec->euid;security_task_getsecid (current, &as->secid);if (!is_in) { if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
fs/dquot.c +2 -1
@@ -955,7 +955,8 @@ static void send_warning(const struct dquot *dquot, const char warntype) MINOR(dquot->dq_sb->s_dev));if (ret) goto attr_err_out; - ret =nla_put_u64 (skb,QUOTA_NL_A_CAUSED_ID , current->user->uid); + ret =nla_put_u64 (skb,QUOTA_NL_A_CAUSED_ID , + current->act_as->user->uid);if (ret) goto attr_err_out;genlmsg_end (skb, msg_head);
kernel/sched.c +1 -1
@@ -204,7 +204,7 @@ static inline struct task_group *task_group(struct task_struct *p)struct task_group *tg;#ifdef CONFIG_FAIR_USER_SCHED - tg = p->user->tg; + tg = p->sec->user->tg;#elif defined(CONFIG_FAIR_CGROUP_SCHED ) tg =container_of (task_subsys_state (p, cpu_cgroup_subsys_id), struct task_group, css);
kernel/tsacct.c +2 -2
@@ -53,8 +53,8 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) stats->ac_flag |=AXSIG ; stats->ac_nice =task_nice (tsk); stats->ac_sched = tsk->policy; - stats->ac_uid = tsk->uid; - stats->ac_gid = tsk->gid; + stats->ac_uid = tsk->sec->uid; + stats->ac_gid = tsk->sec->gid; stats->ac_pid = tsk->pid;rcu_read_lock (); stats->ac_ppid = pid_alive(tsk) ?
mm/mempolicy.c +5 -2
@@ -941,6 +941,7 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,const unsigned long __user *old_nodes, const unsigned long __user *new_nodes) { + struct task_security *act_as, *obj;struct mm_struct *mm;struct task_struct *task;nodemask_t old;
@@ -975,8 +976,10 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,* capabilities, superuser privileges or the same * userid as the target process. */ -if ((current->euid != task->suid) && (current->euid != task->uid) && - (current->uid != task->suid) && (current->uid != task->uid) && + act_as = current->act_as; + obj = task->sec; +if ((act_as->euid != obj->suid) && (act_as->euid != obj->uid) && + (act_as->uid != obj->suid) && (act_as->uid != obj->uid) && !capable (CAP_SYS_NICE )) { err = -EPERM ; goto out;
mm/migrate.c +5 -2
@@ -909,6 +909,7 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,const int __user *nodes, int __user *status, int flags) { + struct task_security *act_as, *obj;int err =0 ;int i;struct task_struct *task;
@@ -942,8 +943,10 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,* capabilities, superuser privileges or the same * userid as the target process. */ -if ((current->euid != task->suid) && (current->euid != task->uid) && - (current->uid != task->suid) && (current->uid != task->uid) && + act_as = current->act_as; + obj = task->sec; +if ((act_as->euid != obj->suid) && (act_as->euid != obj->uid) && + (act_as->uid != obj->suid) && (act_as->uid != obj->uid) && !capable (CAP_SYS_NICE )) { err = -EPERM ; goto out2;
net/ax25/af_ax25.c +1 -1
@@ -1052,7 +1052,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)if (addr->fsa_ax25.sax25_family !=AF_AX25 )return -EINVAL ; - user =ax25_findbyuid (current->euid); + user =ax25_findbyuid (current->act_as->euid);if (user) { call = user->call;ax25_uid_put (user);
net/ax25/ax25_route.c +1 -1
@@ -419,7 +419,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) goto put; } - user =ax25_findbyuid (current->euid); + user =ax25_findbyuid (current->act_as->euid);if (user) { ax25->source_addr = user->call;ax25_uid_put (user);
net/ipv6/ip6_flowlabel.c +1 -1
@@ -364,7 +364,7 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int * fl->owner = current->pid;break ;case IPV6_FL_S_USER : - fl->owner = current->euid; + fl->owner = current->act_as->euid;break ;default : err = -EINVAL ;
net/netrom/af_netrom.c +2 -2
@@ -599,7 +599,7 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) }else { source = &addr->fsa_ax25.sax25_call; - user =ax25_findbyuid (current->euid); + user =ax25_findbyuid (current->act_as->euid);if (user) { nr->user_addr = user->call;ax25_uid_put (user);
@@ -673,7 +673,7 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, } source = (ax25_address *)dev->dev_addr; - user =ax25_findbyuid (current->euid); + user =ax25_findbyuid (current->act_as->euid);if (user) { nr->user_addr = user->call;ax25_uid_put (user);
net/rose/af_rose.c +2 -2
@@ -670,7 +670,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) source = &addr->srose_call; - user =ax25_findbyuid (current->euid); + user =ax25_findbyuid (current->act_as->euid);if (user) { rose->source_call = user->call;ax25_uid_put (user);
@@ -769,7 +769,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le goto out_release; } - user =ax25_findbyuid (current->euid); + user =ax25_findbyuid (current->act_as->euid);if (!user) { err = -EINVAL ; goto out_release;
security/commoncap.c +4 -3
@@ -513,7 +513,8 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,*/ static inline int cap_safe_nice (struct task_struct *p) { -if (!cap_issubset (p->cap_permitted, current->cap_permitted) && +if (!cap_issubset (p->sec->cap_permitted, + current->act_as->cap_permitted) && !__capable (current,CAP_SYS_NICE ))return -EPERM ;return 0 ;
@@ -547,7 +548,7 @@ int cap_task_kill(struct task_struct *p, struct siginfo *info,* allowed. * We must preserve legacy signal behavior in this case. */ -if (p->euid ==0 && p->uid == current->uid) +if (p->sec->euid ==0 && p->sec->uid == current->act_as->uid)return 0 ;/* sigcont is permitted within same session */
@@ -562,7 +563,7 @@ int cap_task_kill(struct task_struct *p, struct siginfo *info,* Used only by usb drivers? */ return 0 ; -if (cap_issubset (p->cap_permitted, current->cap_permitted)) +if (cap_issubset (p->sec->cap_permitted, current->act_as->cap_permitted))return 0 ;if (capable (CAP_KILL ))return 0 ;
security/selinux/xfrm.c +3 -3
@@ -198,7 +198,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *uctx, u32 sid) { int rc = 0; -struct task_security_struct *tsec = current->security; +struct task_security_struct *tsec = current->act_as->security;struct xfrm_sec_ctx *ctx =NULL ;char *ctx_str =NULL ;u32 str_len;
@@ -336,7 +336,7 @@ void selinux_xfrm_policy_free(struct xfrm_policy *xp)*/ int selinux_xfrm_policy_delete (struct xfrm_policy *xp) { -struct task_security_struct *tsec = current->security; +struct task_security_struct *tsec = current->act_as->security;struct xfrm_sec_ctx *ctx = xp->security;int rc =0 ;
@@ -378,7 +378,7 @@ void selinux_xfrm_state_free(struct xfrm_state *x)*/ int selinux_xfrm_state_delete (struct xfrm_state *x) { -struct task_security_struct *tsec = current->security; +struct task_security_struct *tsec = current->act_as->security;struct xfrm_sec_ctx *ctx = x->security;int rc =0 ;
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 1/1 Security: Make NFSD work with detached security
In reply to David HowellsMake NFSD work with detached security, using the patches that excise the security information from task_struct to struct task_security as a base.
Each time NFSD wants a new security descriptor (to do NFS4 recovery or just to do NFS operations), a task_security record is derived from NFSD's *objective* security, modified and then applied as the *subjective* security. This means
(a) the changes are not visible to anyone looking at NFSD through /proc, (b) there is no leakage between two consecutive ops with different security configurations.
Consideration should probably be given to caching the task_security record on the basis that there'll probably be several ops that will want to use any particular security configuration.
Furthermore, nfs4recover.c perhaps ought to set an appropriate LSM context on the record pointed to by rec_security so that the disk is accessed appropriately (see set_security_override[_from_ctx]()).
NOTE! This patch must be and will be rolled in to patch 06 of 26 to make the latter compile fully, however it may be useful to the nfsd maintainers to see it as a separate patch.
---
fs/nfsd/auth.c | 31 +++++++++++++++++------- fs/nfsd/nfs4recover.c | 64 +++++++++++++++++++++++++++++++------------------ include/linux/sched.h | 1 + kernel/sys.c | 27 ++++++++++++++++++--- 4 files changed, 86 insertions(+), 37 deletions(-)
fs/nfsd/auth.c +22 -9
@@ -6,6 +6,7 @@#include <linux/types.h> #include <linux/sched.h> +#include <linux/cred.h> #include <linux/sunrpc/svc.h> #include <linux/sunrpc/svcauth.h> #include <linux/nfsd/nfsd.h>
@@ -28,11 +29,17 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)int nfsd_setuser (struct svc_rqst *rqstp,struct svc_export *exp) { +struct task_security *sec, *old;struct svc_cred cred = rqstp->rq_cred;int i;int flags =nfsexp_flags (rqstp, exp);int ret; +/* derive the new security record from nfsd's objective security */ + sec =get_kernel_security (current); +if (!sec) +return -ENOMEM ; +if (flags &NFSEXP_ALLSQUASH ) { cred.cr_uid = exp->ex_anon_uid; cred.cr_gid = exp->ex_anon_gid;
@@ -56,23 +63,29 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)get_group_info (cred.cr_group_info);if (cred.cr_uid != (uid_t) -1 ) - current->fsuid = cred.cr_uid; + sec->fsuid = cred.cr_uid;else - current->fsuid = exp->ex_anon_uid; + sec->fsuid = exp->ex_anon_uid;if (cred.cr_gid != (gid_t) -1 ) - current->fsgid = cred.cr_gid; + sec->fsgid = cred.cr_gid;else - current->fsgid = exp->ex_anon_gid; + sec->fsgid = exp->ex_anon_gid; -if (!cred.cr_group_info) +if (!cred.cr_group_info) { +put_task_security (sec);return -ENOMEM ; - ret =set_current_groups (cred.cr_group_info); + } + ret =set_groups (sec, cred.cr_group_info);put_group_info (cred.cr_group_info);if ((cred.cr_uid)) { -cap_t (current->cap_effective) &= ~CAP_NFSD_MASK ; +cap_t (sec->cap_effective) &= ~CAP_NFSD_MASK ; }else { -cap_t (current->cap_effective) |= (CAP_NFSD_MASK & - current->cap_permitted); +cap_t (sec->cap_effective) |=CAP_NFSD_MASK & sec->cap_permitted; } + +/* set the new security as nfsd's subjective security */ + old = current->act_as; + current->act_as = sec; +put_task_security (old);return ret; }
fs/nfsd/nfs4recover.c +40 -24
161 lines not on this page · raw message
include/linux/sched.h +1 -0
@@ -886,6 +886,7 @@ struct group_info {extern struct group_info *groups_alloc (int gidsetsize);extern void groups_free (struct group_info *group_info);extern int set_current_groups (struct group_info *group_info); +extern int set_groups (struct task_security *sec,struct group_info *group_info);extern int groups_search (struct group_info *group_info,gid_t grp);/* access the groups "array" with this macro */ #define GROUP_AT (gi, i) \
kernel/sys.c +23 -4
@@ -1245,10 +1245,16 @@ int groups_search(struct group_info *group_info, gid_t grp)return 0 ; } -/* validate and set current->group_info */ -int set_current_groups (struct group_info *group_info) +/** +* set_groups - Change a group subscription in a security record +* @sec: The security record to alter +* @group_info: The group list to impose +* +* Validate a group subscription and, if valid, impose it upon a task security +* record. +*/ +int set_groups (struct task_security *sec,struct group_info *group_info) { -struct task_security *sec = current->sec;int retval;struct group_info *old_info;
@@ -1265,10 +1271,23 @@ int set_current_groups(struct group_info *group_info)spin_unlock (&sec->lock);put_group_info (old_info); -return 0 ; } +EXPORT_SYMBOL (set_groups); + +/** +* set_current_groups - Change current's group subscription +* @group_info: The group list to impose +* +* Validate a group subscription and, if valid, impose it upon current's task +* security record. +*/ +int set_current_groups (struct group_info *group_info) +{ +return set_groups (current->sec, group_info); +} +EXPORT_SYMBOL (set_current_groups);asmlinkage long sys_getgroups (int gidsetsize,gid_t __user *grouplist)
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Re: [PATCH 06b/26] Security: Make NFSD work with detached security
Quoted 11 lines · David Howells
Make NFSD work with detached security, using the patches that excise the security information from
task_structto structtask_securityas a base.Each time NFSD wants a new security descriptor (to do NFS4 recovery or just to do NFS operations), a
task_securityrecord is derived from NFSD's *objective* security, modified and then applied as the *subjective* security. This means
(a) the changes are not visible to anyone looking at NFSD through /proc, (b) there is no leakage between two consecutive ops with different security configurations.
Quoted 3 lines
Consideration should probably be given to caching the
task_securityrecord on the basis that there'll probably be several ops that will want to use any particular security configuration.
Just curious--why? Are get_kernel_security(), etc., particularly expensive?
--b.
Quoted 325 lines
Furthermore,
nfs4recover.cperhaps ought to set an appropriate LSM context on the record pointed to byrec_securityso that the disk is accessed appropriately (see set_security_override[_from_ctx]()).NOTE! This patch must be and will be rolled in to patch 06 of 26 to make the latter compile fully, however it may be useful to the nfsd maintainers to see it as a separate patch.
Signed-off-by David Howells <[email protected]>---
fs/nfsd/auth.c | 31 +++++++++++++++++------- fs/nfsd/nfs4recover.c | 64 +++++++++++++++++++++++++++++++------------------ include/linux/sched.h | 1 + kernel/sys.c | 27 ++++++++++++++++++--- 4 files changed, 86 insertions(+), 37 deletions(-)fs/nfsd/auth.c +22
-9@@ -6,6 +6,7 @@#include <linux/types.h> #include <linux/sched.h> +#include <linux/cred.h> #include <linux/sunrpc/svc.h> #include <linux/sunrpc/svcauth.h> #include <linux/nfsd/nfsd.h> @@ -28,11 +29,17 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)int nfsd_setuser (struct svc_rqst *rqstp,struct svc_export *exp) { +struct task_security *sec, *old;struct svc_cred cred = rqstp->rq_cred;int i;int flags =nfsexp_flags (rqstp, exp);int ret; +/* derive the new security record from nfsd's objective security */ + sec =get_kernel_security (current); +if (!sec) +return -ENOMEM ; +if (flags &NFSEXP_ALLSQUASH ) { cred.cr_uid = exp->ex_anon_uid; cred.cr_gid = exp->ex_anon_gid;@@ -56,23 +63,29 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)get_group_info (cred.cr_group_info);if (cred.cr_uid != (uid_t) -1 ) - current->fsuid = cred.cr_uid; + sec->fsuid = cred.cr_uid;else - current->fsuid = exp->ex_anon_uid; + sec->fsuid = exp->ex_anon_uid;if (cred.cr_gid != (gid_t) -1 ) - current->fsgid = cred.cr_gid; + sec->fsgid = cred.cr_gid;else - current->fsgid = exp->ex_anon_gid; + sec->fsgid = exp->ex_anon_gid; -if (!cred.cr_group_info) +if (!cred.cr_group_info) { +put_task_security (sec);return -ENOMEM ; - ret =set_current_groups (cred.cr_group_info); + } + ret =set_groups (sec, cred.cr_group_info);put_group_info (cred.cr_group_info);if ((cred.cr_uid)) { -cap_t (current->cap_effective) &= ~CAP_NFSD_MASK ; +cap_t (sec->cap_effective) &= ~CAP_NFSD_MASK ; }else { -cap_t (current->cap_effective) |= (CAP_NFSD_MASK & - current->cap_permitted); +cap_t (sec->cap_effective) |=CAP_NFSD_MASK & sec->cap_permitted; } + +/* set the new security as nfsd's subjective security */ + old = current->act_as; + current->act_as = sec; +put_task_security (old);return ret; }fs/nfsd/nfs4recover.c +40
-24@@ -46,27 +46,37 @@#include <linux/scatterlist.h> #include <linux/crypto.h> #include <linux/sched.h> +#include <linux/cred.h> #define NFSDDBG_FACILITY NFSDDBG_PROC/* Globals */ static struct nameidata rec_dir;static int rec_dir_init =0 ; +static struct task_security *rec_security; +/* +* switch the special recovery access security in on the current task's +* subjective security +*/ static void -nfs4_save_user (uid_t *saveuid,gid_t *savegid) +nfs4_begin_secure (struct task_security **saved_sec) { - *saveuid = current->fsuid; - *savegid = current->fsgid; - current->fsuid =0 ; - current->fsgid =0 ; + *saved_sec = current->act_as; + current->act_as =get_task_security (rec_security); } +/* +* return the current task's subjective security to its former glory +*/ static void -nfs4_reset_user (uid_t saveuid,gid_t savegid) +nfs4_end_secure (struct task_security *saved_sec) { - current->fsuid = saveuid; - current->fsgid = savegid; +struct task_security *discard; + + discard = current->act_as; + current->act_as = saved_sec; +put_task_security (discard); } static void@@ -128,10 +138,9 @@ nfsd4_sync_rec_dir(void)int nfsd4_create_clid_dir (struct nfs4_client *clp) { +struct task_security *saved_sec;char *dname = clp->cl_recdir;struct dentry *dentry; -uid_t uid; -gid_t gid;int status;dprintk ("NFSD: nfsd4_create_clid_dir for \"%s\"\n" , dname);@@ -139,7 +148,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)if (!rec_dir_init || clp->cl_firststate)return 0 ; -nfs4_save_user (&uid, &gid); +nfs4_begin_secure (&saved_sec);/* lock the parent */ mutex_lock (&rec_dir.dentry->d_inode->i_mutex);@@ -163,7 +172,7 @@ out_unlock: clp->cl_firststate =1 ;nfsd4_sync_rec_dir (); } -nfs4_reset_user (uid, gid); +nfs4_end_secure (saved_sec);dprintk ("NFSD: nfsd4_create_clid_dir returns %d\n" , status);return status; }@@ -206,20 +215,19 @@ nfsd4_build_dentrylist(void *arg, const char *name, int namlen,static int nfsd4_list_rec_dir (struct dentry *dir,recdir_func *f) { +struct task_security *saved_sec;struct file *filp;struct dentry_list_arg dla = { .parent = dir, };struct list_head *dentries = &dla.dentries;struct dentry_list *child; -uid_t uid; -gid_t gid;int status;if (!rec_dir_init)return 0 ; -nfs4_save_user (&uid, &gid); +nfs4_begin_secure (&saved_sec); filp =dentry_open (dget (dir),mntget (rec_dir.mnt),O_RDONLY ); status =PTR_ERR (filp);@@ -244,7 +252,7 @@ out:dput (child->dentry);kfree (child); } -nfs4_reset_user (uid, gid); +nfs4_end_secure (saved_sec);return status; }@@ -306,17 +314,16 @@ out:void nfsd4_remove_clid_dir (struct nfs4_client *clp) { -uid_t uid; -gid_t gid; +struct task_security *saved_sec;int status;if (!rec_dir_init || !clp->cl_firststate)return ; clp->cl_firststate =0 ; -nfs4_save_user (&uid, &gid); +nfs4_begin_secure (&saved_sec); status =nfsd4_unlink_clid_dir (clp->cl_recdir,HEXDIR_LEN -1 ); -nfs4_reset_user (uid, gid); +nfs4_end_secure (saved_sec);if (status ==0 )nfsd4_sync_rec_dir ();if (status)@@ -387,8 +394,7 @@ nfsd4_recdir_load(void) {void nfsd4_init_recdir (char *rec_dirname) { -uid_t uid =0 ; -gid_t gid =0 ; +struct task_security *saved_sec;int status; printk("NFSD: Using %s as the NFSv4 state recovery directory\n",@@ -396,7 +402,15 @@ nfsd4_init_recdir(char *rec_dirname)BUG_ON (rec_dir_init); -nfs4_save_user (&uid, &gid); +/* derive the security record from this task's objective security */ + rec_security =get_kernel_security (current); +if (!rec_security) { +printk ("NFSD:" +" unable to allocate recovery directory security\n" ); +return ; + } + +nfs4_begin_secure (&saved_sec); status =path_lookup (rec_dirname,LOOKUP_FOLLOW |LOOKUP_DIRECTORY , &rec_dir);@@ -406,7 +420,8 @@ nfsd4_init_recdir(char *rec_dirname)if (!status) rec_dir_init =1 ; -nfs4_reset_user (uid, gid); + +nfs4_end_secure (saved_sec); }void @@ -416,4 +431,5 @@ nfsd4_shutdown_recdir(void)return ; rec_dir_init =0 ;path_release (&rec_dir); +put_task_security (rec_security); }include/linux/sched.h +1
-0@@ -886,6 +886,7 @@ struct group_info {extern struct group_info *groups_alloc (int gidsetsize);extern void groups_free (struct group_info *group_info);extern int set_current_groups (struct group_info *group_info); +extern int set_groups (struct task_security *sec,struct group_info *group_info);extern int groups_search (struct group_info *group_info,gid_t grp);/* access the groups "array" with this macro */ #define GROUP_AT (gi, i) \kernel/sys.c +23
-4@@ -1245,10 +1245,16 @@ int groups_search(struct group_info *group_info, gid_t grp)return 0 ; } -/* validate and set current->group_info */ -int set_current_groups (struct group_info *group_info) +/** +* set_groups - Change a group subscription in a security record +* @sec: The security record to alter +* @group_info: The group list to impose +* +* Validate a group subscription and, if valid, impose it upon a task security +* record. +*/ +int set_groups (struct task_security *sec,struct group_info *group_info) { -struct task_security *sec = current->sec;int retval;struct group_info *old_info;@@ -1265,10 +1271,23 @@ int set_current_groups(struct group_info *group_info)spin_unlock (&sec->lock);put_group_info (old_info); -return 0 ; } +EXPORT_SYMBOL (set_groups); + +/** +* set_current_groups - Change current's group subscription +* @group_info: The group list to impose +* +* Validate a group subscription and, if valid, impose it upon current's task +* security record. +*/ +int set_current_groups (struct group_info *group_info) +{ +return set_groups (current->sec, group_info); +} +EXPORT_SYMBOL (set_current_groups);asmlinkage long sys_getgroups (int gidsetsize,gid_t __user *grouplist)
David Howells
maintainerRe: [PATCH 06b/26] Security: Make NFSD work with detached security
Quoted 2 lines · J. Bruce Fields
Just curious--why? Are
get_kernel_security(), etc., particularly expensive?
It involves a kmalloc(). That means an extra possibility for an error. Plus it may allow you to cache the result of checking whether, say, SELinux security labels are allowed to be set when passed over NFS (if such is possible).
David
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerRe: [PATCH 06b/26] Security: Make NFSD work with detached security
Quoted 9 lines · David Howells
Quoted 2 lines · J. Bruce Fields
Just curious--why? Are
get_kernel_security(), etc., particularly expensive?It involves a
kmalloc(). That means an extra possibility for an error. Plus it may allow you to cache the result of checking whether, say, SELinux security labels are allowed to be set when passed over NFS (if such is possible).
Apart from that, though, no, it's not particularly expensive.
David
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerRe: [NFS] [PATCH 06b/26] Security: Make NFSD work with detached security
In reply to J. Bruce FieldsQuoted 2 lines · J. Bruce Fields
Just curious--why? Are
get_kernel_security(), etc., particularly expensive?
It involves a kmalloc(). That means an extra possibility for an error. Plus it may allow you to cache the result of checking whether, say, SELinux security labels are allowed to be set when passed over NFS (if such is possible).
David
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs
_______________________________________________
Please note that [email protected] is being discontinued. Please subscribe to [email protected] instead.
http://vger.kernel.org/vger-lists.html#linux-nfs
Re: [NFS] [PATCH 06b/26] Security: Make NFSD work with detached security
In reply to David HowellsQuoted 11 lines · David Howells
Make NFSD work with detached security, using the patches that excise the security information from
task_structto structtask_securityas a base.Each time NFSD wants a new security descriptor (to do NFS4 recovery or just to do NFS operations), a
task_securityrecord is derived from NFSD's *objective* security, modified and then applied as the *subjective* security. This means
(a) the changes are not visible to anyone looking at NFSD through /proc, (b) there is no leakage between two consecutive ops with different security configurations.
Quoted 3 lines
Consideration should probably be given to caching the
task_securityrecord on the basis that there'll probably be several ops that will want to use any particular security configuration.
Just curious--why? Are get_kernel_security(), etc., particularly expensive?
--b.
Quoted 315 lines
Furthermore,
nfs4recover.cperhaps ought to set an appropriate LSM context on the record pointed to byrec_securityso that the disk is accessed appropriately (see set_security_override[_from_ctx]()).NOTE! This patch must be and will be rolled in to patch 06 of 26 to make the latter compile fully, however it may be useful to the nfsd maintainers to see it as a separate patch.
Signed-off-by David Howells <[email protected]>---
fs/nfsd/auth.c | 31 +++++++++++++++++------- fs/nfsd/nfs4recover.c | 64 +++++++++++++++++++++++++++++++------------------ include/linux/sched.h | 1 + kernel/sys.c | 27 ++++++++++++++++++--- 4 files changed, 86 insertions(+), 37 deletions(-)fs/nfsd/auth.c +22
-9@@ -6,6 +6,7 @@#include <linux/types.h> #include <linux/sched.h> +#include <linux/cred.h> #include <linux/sunrpc/svc.h> #include <linux/sunrpc/svcauth.h> #include <linux/nfsd/nfsd.h> @@ -28,11 +29,17 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)int nfsd_setuser (struct svc_rqst *rqstp,struct svc_export *exp) { +struct task_security *sec, *old;struct svc_cred cred = rqstp->rq_cred;int i;int flags =nfsexp_flags (rqstp, exp);int ret; +/* derive the new security record from nfsd's objective security */ + sec =get_kernel_security (current); +if (!sec) +return -ENOMEM ; +if (flags &NFSEXP_ALLSQUASH ) { cred.cr_uid = exp->ex_anon_uid; cred.cr_gid = exp->ex_anon_gid;@@ -56,23 +63,29 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)get_group_info (cred.cr_group_info);if (cred.cr_uid != (uid_t) -1 ) - current->fsuid = cred.cr_uid; + sec->fsuid = cred.cr_uid;else - current->fsuid = exp->ex_anon_uid; + sec->fsuid = exp->ex_anon_uid;if (cred.cr_gid != (gid_t) -1 ) - current->fsgid = cred.cr_gid; + sec->fsgid = cred.cr_gid;else - current->fsgid = exp->ex_anon_gid; + sec->fsgid = exp->ex_anon_gid; -if (!cred.cr_group_info) +if (!cred.cr_group_info) { +put_task_security (sec);return -ENOMEM ; - ret =set_current_groups (cred.cr_group_info); + } + ret =set_groups (sec, cred.cr_group_info);put_group_info (cred.cr_group_info);if ((cred.cr_uid)) { -cap_t (current->cap_effective) &= ~CAP_NFSD_MASK ; +cap_t (sec->cap_effective) &= ~CAP_NFSD_MASK ; }else { -cap_t (current->cap_effective) |= (CAP_NFSD_MASK & - current->cap_permitted); +cap_t (sec->cap_effective) |=CAP_NFSD_MASK & sec->cap_permitted; } + +/* set the new security as nfsd's subjective security */ + old = current->act_as; + current->act_as = sec; +put_task_security (old);return ret; }fs/nfsd/nfs4recover.c +40
-24@@ -46,27 +46,37 @@#include <linux/scatterlist.h> #include <linux/crypto.h> #include <linux/sched.h> +#include <linux/cred.h> #define NFSDDBG_FACILITY NFSDDBG_PROC/* Globals */ static struct nameidata rec_dir;static int rec_dir_init =0 ; +static struct task_security *rec_security; +/* +* switch the special recovery access security in on the current task's +* subjective security +*/ static void -nfs4_save_user (uid_t *saveuid,gid_t *savegid) +nfs4_begin_secure (struct task_security **saved_sec) { - *saveuid = current->fsuid; - *savegid = current->fsgid; - current->fsuid =0 ; - current->fsgid =0 ; + *saved_sec = current->act_as; + current->act_as =get_task_security (rec_security); } +/* +* return the current task's subjective security to its former glory +*/ static void -nfs4_reset_user (uid_t saveuid,gid_t savegid) +nfs4_end_secure (struct task_security *saved_sec) { - current->fsuid = saveuid; - current->fsgid = savegid; +struct task_security *discard; + + discard = current->act_as; + current->act_as = saved_sec; +put_task_security (discard); } static void@@ -128,10 +138,9 @@ nfsd4_sync_rec_dir(void)int nfsd4_create_clid_dir (struct nfs4_client *clp) { +struct task_security *saved_sec;char *dname = clp->cl_recdir;struct dentry *dentry; -uid_t uid; -gid_t gid;int status;dprintk ("NFSD: nfsd4_create_clid_dir for \"%s\"\n" , dname);@@ -139,7 +148,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)if (!rec_dir_init || clp->cl_firststate)return 0 ; -nfs4_save_user (&uid, &gid); +nfs4_begin_secure (&saved_sec);/* lock the parent */ mutex_lock (&rec_dir.dentry->d_inode->i_mutex);@@ -163,7 +172,7 @@ out_unlock: clp->cl_firststate =1 ;nfsd4_sync_rec_dir (); } -nfs4_reset_user (uid, gid); +nfs4_end_secure (saved_sec);dprintk ("NFSD: nfsd4_create_clid_dir returns %d\n" , status);return status; }@@ -206,20 +215,19 @@ nfsd4_build_dentrylist(void *arg, const char *name, int namlen,static int nfsd4_list_rec_dir (struct dentry *dir,recdir_func *f) { +struct task_security *saved_sec;struct file *filp;struct dentry_list_arg dla = { .parent = dir, };struct list_head *dentries = &dla.dentries;struct dentry_list *child; -uid_t uid; -gid_t gid;int status;if (!rec_dir_init)return 0 ; -nfs4_save_user (&uid, &gid); +nfs4_begin_secure (&saved_sec); filp =dentry_open (dget (dir),mntget (rec_dir.mnt),O_RDONLY ); status =PTR_ERR (filp);@@ -244,7 +252,7 @@ out:dput (child->dentry);kfree (child); } -nfs4_reset_user (uid, gid); +nfs4_end_secure (saved_sec);return status; }@@ -306,17 +314,16 @@ out:void nfsd4_remove_clid_dir (struct nfs4_client *clp) { -uid_t uid; -gid_t gid; +struct task_security *saved_sec;int status;if (!rec_dir_init || !clp->cl_firststate)return ; clp->cl_firststate =0 ; -nfs4_save_user (&uid, &gid); +nfs4_begin_secure (&saved_sec); status =nfsd4_unlink_clid_dir (clp->cl_recdir,HEXDIR_LEN -1 ); -nfs4_reset_user (uid, gid); +nfs4_end_secure (saved_sec);if (status ==0 )nfsd4_sync_rec_dir ();if (status)@@ -387,8 +394,7 @@ nfsd4_recdir_load(void) {void nfsd4_init_recdir (char *rec_dirname) { -uid_t uid =0 ; -gid_t gid =0 ; +struct task_security *saved_sec;int status; printk("NFSD: Using %s as the NFSv4 state recovery directory\n",@@ -396,7 +402,15 @@ nfsd4_init_recdir(char *rec_dirname)BUG_ON (rec_dir_init); -nfs4_save_user (&uid, &gid); +/* derive the security record from this task's objective security */ + rec_security =get_kernel_security (current); +if (!rec_security) { +printk ("NFSD:" +" unable to allocate recovery directory security\n" ); +return ; + } + +nfs4_begin_secure (&saved_sec); status =path_lookup (rec_dirname,LOOKUP_FOLLOW |LOOKUP_DIRECTORY , &rec_dir);@@ -406,7 +420,8 @@ nfsd4_init_recdir(char *rec_dirname)if (!status) rec_dir_init =1 ; -nfs4_reset_user (uid, gid); + +nfs4_end_secure (saved_sec); }void @@ -416,4 +431,5 @@ nfsd4_shutdown_recdir(void)return ; rec_dir_init =0 ;path_release (&rec_dir); +put_task_security (rec_security); }include/linux/sched.h +1
-0@@ -886,6 +886,7 @@ struct group_info {extern struct group_info *groups_alloc (int gidsetsize);extern void groups_free (struct group_info *group_info);extern int set_current_groups (struct group_info *group_info); +extern int set_groups (struct task_security *sec,struct group_info *group_info);extern int groups_search (struct group_info *group_info,gid_t grp);/* access the groups "array" with this macro */ #define GROUP_AT (gi, i) \kernel/sys.c +16
-4@@ -1245,10 +1245,16 @@ int groups_search(struct group_info *group_info, gid_t grp)return 0 ; } -/* validate and set current->group_info */ -int set_current_groups (struct group_info *group_info) +/** +* set_groups - Change a group subscription in a security record +* @sec: The security record to alter +* @group_info: The group list to impose +* +* Validate a group subscription and, if valid, impose it upon a task security +* record. +*/ +int set_groups (struct task_security *sec,struct group_info *group_info) { -struct task_security *sec = current->sec;int retval;struct group_info *old_info;@@ -1265,10 +1271,23 @@ int set_current_groups(struct group_info *group_info)spin_unlock (&sec->lock);put_group_info (old_info); -return 0 ; } +EXPORT_SYMBOL (set_groups); + +/** +* set_current_groups - Change current's group subscription +* @group_info: The group list to impose +* +* Validate a group subscription and, if valid, impose it upon current's task
kernel/sys.c int set_current_groups(struct group_info *group_info) · line 1293
Quoted 10 lines
kernel/sys.c +7
-0+* security record. +*/ +int set_current_groups (struct group_info *group_info) +{ +return set_groups (current->sec, group_info); +} +EXPORT_SYMBOL (set_current_groups);asmlinkage long sys_getgroups (int gidsetsize,gid_t __user *grouplist)
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs
_______________________________________________
Please note that [email protected] is being discontinued. Please subscribe to [email protected] instead.
http://vger.kernel.org/vger-lists.html#linux-nfs
David Howells
maintainerPATCH 7/26 Security: De-embed task security record from task and use refcounting
In reply to David HowellsRemove the temporarily embedded task security record from task_struct. Instead it is made to dangle from the task_struct::sec and task_struct::act_as pointers with references counted for each.
do_coredump() is made to create a copy of the security record, modify it and then use that to override the main one for a task. sys_faccessat() is made to do the same.
The process and session keyrings are moved from signal_struct into a new thread_group_security struct. This is then refcounted, with pointers coming from the task_security struct instead of from signal_struct.
The keyring functions then take pointers to task_security structs rather than task_structs for their security contexts. This is so that request_key() can proceed asynchronously without having to worry about the initiator task's act_as pointer changing.
The LSM hooks for dealing with task security are modified to deal with the task security struct directly rather than going via the task_struct as appopriate.
This permits the subjective security context of a task to be overridden by changing its act_as pointer without altering its objective security pointer, and thus not breaking signalling, ptrace, etc. whilst the override is in force.
---
fs/exec.c | 15 +- fs/open.c | 37 ++--- include/linux/init_task.h | 17 -- include/linux/key-ui.h | 10 + include/linux/key.h | 31 +--- include/linux/sched.h | 40 ++++- include/linux/security.h | 43 ++++-- kernel/Makefile | 2 kernel/cred.c | 139 ++++++++++++++++++ kernel/exit.c | 1 kernel/fork.c | 40 ++--- kernel/kmod.c | 10 + kernel/sys.c | 16 +- kernel/user.c | 2 net/rxrpc/ar-key.c | 4 - security/dummy.c | 14 +- security/keys/internal.h | 10 + security/keys/key.c | 6 - security/keys/keyctl.c | 6 - security/keys/keyring.c | 14 +- security/keys/permission.c | 5 - security/keys/proc.c | 2 security/keys/process_keys.c | 290 +++++++++++++++++--------------------- security/keys/request_key.c | 59 ++++---- security/keys/request_key_auth.c | 38 ++--- security/security.c | 20 ++- security/selinux/hooks.c | 46 +++++- 27 files changed, 526 insertions(+), 391 deletions(-) create mode 100644 kernel/cred.c
fs/exec.c +11 -4
@@ -1674,13 +1674,13 @@ int get_dumpable(struct mm_struct *mm)int do_coredump (long signr,int exit_code,struct pt_regs * regs) { +struct task_security *sec, *old_act_as;char corename[CORENAME_MAX_SIZE +1 ];struct mm_struct *mm = current->mm;struct linux_binfmt * binfmt;struct inode * inode;struct file * file;int retval =0 ; -int fsuid =current_fsuid ();int flag =0 ;int ispipe =0 ;unsigned long core_limit = current->signal->rlim[RLIMIT_CORE ].rlim_cur;
@@ -1692,7 +1692,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) binfmt = current->binfmt;if (!binfmt || !binfmt->core_dump) - goto fail; + goto fail_nosubj; + sec =dup_task_security (current->sec); +if (!sec) + goto fail_nosubj;down_write (&mm->mmap_sem);/* * If another thread got here first, or we are not dumpable, bail out.
@@ -1707,9 +1710,11 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)* process nor do we know its entire history. We only know it * was tainted so we dump it as root in mode 2. */ + old_act_as = current->act_as;if (get_dumpable (mm) ==2 ) {/* Setuid core dump mode */ flag =O_EXCL ;/* Stop rewrite attacks */ - current->act_as->fsuid =0 ;/* Dump root private */ + sec->fsuid =0 ;/* Dump root private */ + current->act_as = sec; } retval =coredump_wait (exit_code);
@@ -1805,8 +1810,10 @@ fail_unlock:if (helper_argv)argv_free (helper_argv); - current->act_as->fsuid = fsuid; + current->act_as = old_act_as;complete_all (&mm->core_done); fail: +put_task_security (sec); +fail_nosubj:return retval; }
fs/open.c +14 -23
@@ -420,34 +420,27 @@ out:*/ asmlinkage long sys_faccessat (int dfd,const char __user *filename,int mode) { +struct task_security *sec, *old_act_as;struct nameidata nd; -int old_fsuid, old_fsgid; -kernel_cap_t old_cap;int res;if (mode & ~S_IRWXO )/* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL ; - old_fsuid = current->act_as->fsuid; - old_fsgid = current->act_as->fsgid; - old_cap = current->act_as->cap_effective; + sec =dup_task_security (current->sec); +if (!sec) +return -ENOMEM ; + sec->fsuid = current->sec->uid; + sec->fsgid = current->sec->gid; - current->act_as->fsuid = current->act_as->uid; - current->act_as->fsgid = current->act_as->gid; - -/* -* Clear the capabilities if we switch to a non-root user -* -* FIXME: There is a race here against sys_capset. The -* capabilities can change yet we will restore the old -* value below. We should hold task_capabilities_lock, -* but we cannot because user_path_walk can sleep. -*/ -if (current->act_as->uid) -cap_clear (current->act_as->cap_effective); +/* Clear the capabilities if we switch to a non-root user */ +if (current->sec->uid) +cap_clear (sec->cap_effective);else - current->act_as->cap_effective = current->act_as->cap_permitted; + sec->cap_effective = current->sec->cap_permitted; + old_act_as = current->act_as; + current->act_as = sec; res =__user_walk_fd (dfd, filename,LOOKUP_FOLLOW |LOOKUP_ACCESS , &nd);if (res) goto out;
@@ -464,10 +457,8 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) out_path_release:path_release (&nd); out: - current->act_as->fsuid = old_fsuid; - current->act_as->fsgid = old_fsgid; - current->act_as->cap_effective = old_cap; - + current->act_as = old_act_as; +put_task_security (sec);return res; }
include/linux/init_task.h +2 -15
@@ -116,18 +116,6 @@ extern struct group_info init_groups;extern struct task_security init_task_security; -#define INIT_TASK_SECURITY (p) \ -{ \ - .usage = ATOMIC_INIT(3), \ - .keep_capabilities = 0, \ - .cap_inheritable = CAP_INIT_INH_SET, \ - .cap_permitted = CAP_FULL_SET, \ - .cap_effective = CAP_INIT_EFF_SET, \ - .user = INIT_USER, \ - .group_info = &init_groups, \ - .lock = __SPIN_LOCK_UNLOCKED(p.lock), \ -} -/* * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -157,9 +145,8 @@ extern struct task_security init_task_security; .children = LIST_HEAD_INIT(tsk.children), \ .sibling = LIST_HEAD_INIT(tsk.sibling), \ .group_leader = &tsk, \ - .__temp_sec = INIT_TASK_SECURITY(tsk.__temp_sec), \ - .sec = &tsk.__temp_sec, \ - .act_as = &tsk.__temp_sec, \ + .sec = &init_task_security, \ + .act_as = &init_task_security, \ .comm = "swapper", \ .thread = INIT_THREAD, \ .fs = &init_fs, \
include/linux/key-ui.h +4 -6
@@ -43,15 +43,13 @@ struct keyring_list {* check to see whether permission is granted to use a key in the desired way */ extern int key_task_permission (const key_ref_t key_ref, -struct task_struct *context, +struct task_security *sec,key_perm_t perm); -static inline int key_permission (const key_ref_t key_ref,key_perm_t perm) -{ -return key_task_permission (key_ref, current, perm); -} +#define key_permission (key_ref, perm) \ + key_task_permission((key_ref), current->act_as, (perm)) -extern key_ref_t lookup_user_key (struct task_struct *context, +extern key_ref_t lookup_user_key (struct task_security *sec,key_serial_t id,int create,int partial,key_perm_t perm);
include/linux/key.h +11 -20
@@ -70,6 +70,8 @@ struct key;struct seq_file ;struct user_struct ;struct signal_struct ; +struct task_security ; +struct thread_group_security ;struct key_type ;struct key_owner ;
@@ -178,7 +180,7 @@ struct key {extern struct key *key_alloc (struct key_type *type,const char *desc,uid_t uid,gid_t gid, -struct task_struct *ctx, +struct task_security *sec,key_perm_t perm,unsigned long flags);
@@ -245,7 +247,7 @@ extern int key_unlink(struct key *keyring, struct key *key);extern struct key *keyring_alloc (const char *description,uid_t uid,gid_t gid, -struct task_struct *ctx, +struct task_security *sec,unsigned long flags,struct key *dest);
@@ -267,24 +269,16 @@ extern struct key *key_lookup(key_serial_t id);*/ extern struct key root_user_keyring, root_session_keyring;extern int alloc_uid_keyring (struct user_struct *user, -struct task_struct *ctx); +struct task_security *sec);extern void switch_uid_keyring (struct user_struct *new_user); -extern int copy_keys (unsigned long clone_flags,struct task_struct *tsk); -extern int copy_thread_group_keys (struct task_struct *tsk); -extern void exit_keys (struct task_struct *tsk); -extern void exit_thread_group_keys (struct signal_struct *tg); +extern int copy_thread_group_keys (struct thread_group_security *tgsec);extern int suid_keys (struct task_struct *tsk);extern int exec_keys (struct task_struct *tsk); -extern void key_fsuid_changed (struct task_struct *tsk); -extern void key_fsgid_changed (struct task_struct *tsk); +extern void key_fsuid_changed (struct task_security *sec); +extern void key_fsgid_changed (struct task_security *sec);extern void key_init (void ); - -#define __install_session_keyring (tsk, keyring) \ -({ \ - struct key *old_session = tsk->signal->session_keyring; \ - tsk->signal->session_keyring = keyring; \ - old_session; \ -}) +extern void __install_session_keyring (struct task_struct *tsk, +struct key *keyring);#else /* CONFIG_KEYS */
@@ -298,11 +292,8 @@ extern void key_init(void);#define is_key_possessed (k) 0#define alloc_uid_keyring (u,c) 0#define switch_uid_keyring (u) do { } while(0) -#define __install_session_keyring (t, k) ({ NULL; }) -#define copy_keys (f,t) 0 +#define __install_session_keyring (t, k) do {} while (0)#define copy_thread_group_keys (t) 0 -#define exit_keys (t) do { } while(0) -#define exit_thread_group_keys (tg) do { } while(0)#define suid_keys (t) do { } while(0)#define exec_keys (t) do { } while(0)#define key_fsuid_changed (t) do { } while(0)
include/linux/sched.h +33 -7
@@ -491,12 +491,6 @@ struct signal_struct {struct list_head cpu_timers[3 ]; -/* keep the process-shared keyrings here so that they do the right -* thing in threads created with CLONE_THREAD */ -#ifdef CONFIG_KEYS -struct key *session_keyring;/* keyring inherited over fork */ -struct key *process_keyring;/* keyring private to this process */ -#endif #ifdef CONFIG_BSD_PROCESS_ACCT struct pacct_struct pacct;/* per-process accounting information */ #endif
@@ -572,6 +566,20 @@ extern struct user_struct root_user;/* +* The common security details for a thread group +* - shared by CLONE_THREAD +*/ +#ifdef CONFIG_KEYS +struct thread_group_security { +atomic_t usage; +pid_t tgid;/* thread group process ID */ +spinlock_t lock; +struct key *session_keyring;/* keyring inherited over fork */ +struct key *process_keyring;/* keyring private to this process */ +}; +#endif + +/* * The security context of a task * * The parts of the context break down into two categories:
@@ -613,6 +621,7 @@ struct task_security {* keys to */ struct key *thread_keyring;/* keyring private to this thread */ struct key *request_key_auth;/* assumed request_key authority */ +struct thread_group_security *tgsec;#endif #ifdef CONFIG_SECURITY void *security;/* subjective LSM security */
@@ -622,10 +631,28 @@ struct task_security {spinlock_t lock;/* lock for pointer changes */ }; +extern struct task_security *dup_task_security (struct task_security *); +extern int copy_task_security (struct task_struct *,unsigned long ); +extern void put_task_security (struct task_security *); +#define current_fsuid () (current->act_as->fsuid)#define current_fsgid () (current->act_as->fsgid)#define current_cap () (current->act_as->cap_effective) +/** +* get_task_security - Get an extra reference on a task security record +* @sec: The security record to get the reference on +* +* Get an extra reference on a task security record. The caller must arrange +* for this to be released. +*/ +static inline +struct task_security *get_task_security (struct task_security *sec) +{ +atomic_inc (&sec->usage); +return sec; +} +struct backing_dev_info ;struct reclaim_state ;
@@ -1082,7 +1109,6 @@ struct task_struct {struct list_head cpu_timers[3 ];/* process credentials */ -struct task_security __temp_sec__deprecated ;/* temporary security to be removed */ struct task_security *sec;/* actual/objective task security */ struct task_security *act_as;/* effective/subjective task security */
include/linux/security.h +29 -14
113 lines not on this page · raw message
kernel/Makefile +1 -1
@@ -9,7 +9,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ rcupdate.o extable.o params.o posix-timers.o \ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o rwsem.o latency.o nsproxy.o srcu.o \ - utsname.o notifier.o + utsname.o notifier.o cred.o obj-$(CONFIG_SYSCTL) += sysctl_check.o obj-$(CONFIG_STACKTRACE) += stacktrace.o
kernel/cred.c new file +139 -0
139 lines not on this page · raw message
kernel/exit.c +0 -1
@@ -1000,7 +1000,6 @@ fastcall NORET_TYPE void do_exit(long code)check_stack_usage ();exit_thread ();cgroup_exit (tsk,1 ); -exit_keys (tsk);if (group_dead && tsk->signal->leader)disassociate_ctty (1 );
kernel/fork.c +12 -28
@@ -121,9 +121,8 @@ void __put_task_struct(struct task_struct *tsk)WARN_ON (atomic_read (&tsk->usage));WARN_ON (tsk == current); -security_task_free (tsk); -free_uid (tsk->__temp_sec.user); -put_group_info (tsk->__temp_sec.group_info); +put_task_security (tsk->sec); +put_task_security (tsk->act_as);delayacct_tsk_free (tsk);if (!profile_handoff_task (tsk))
@@ -845,7 +844,6 @@ void __cleanup_sighand(struct sighand_struct *sighand)static int copy_signal (unsigned long clone_flags,struct task_struct *tsk) {struct signal_struct *sig; -int ret;if (clone_flags &CLONE_THREAD ) {atomic_inc (¤t->signal->count);
@@ -857,12 +855,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)if (!sig)return -ENOMEM ; - ret =copy_thread_group_keys (tsk); -if (ret <0 ) { -kmem_cache_free (signal_cachep, sig); -return ret; - } -atomic_set (&sig->count,1 );atomic_set (&sig->live,1 );init_waitqueue_head (&sig->wait_chldexit);
@@ -920,7 +912,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)void __cleanup_signal (struct signal_struct *sig) { -exit_thread_group_keys (sig);kmem_cache_free (signal_cachep, sig); }
@@ -1014,18 +1005,19 @@ static struct task_struct *copy_process(unsigned long clone_flags,DEBUG_LOCKS_WARN_ON (!p->hardirqs_enabled);DEBUG_LOCKS_WARN_ON (!p->softirqs_enabled);#endif - p->act_as = p->sec = &p->__temp_sec; + retval =copy_task_security (p, clone_flags); +if (retval <0 ) + goto bad_fork_free; + retval = -EAGAIN ;if (atomic_read (&p->sec->user->processes) >= p->signal->rlim[RLIMIT_NPROC ].rlim_cur) {if (!capable (CAP_SYS_ADMIN ) && !capable (CAP_SYS_RESOURCE ) && p->sec->user != current->nsproxy->user_ns->root_user) - goto bad_fork_free; + goto bad_fork_cleanup_put_task_sec; } -atomic_inc (&p->sec->user->__count);atomic_inc (&p->sec->user->processes); -get_group_info (p->sec->group_info);/* * If multiple threads are within copy_process(), then this check
@@ -1080,9 +1072,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,do_posix_clock_monotonic_gettime (&p->start_time); p->real_start_time = p->start_time;monotonic_to_bootbased (&p->real_start_time); -#ifdef CONFIG_SECURITY - p->sec->security =NULL ; -#endif p->io_context =NULL ; p->audit_context =NULL ;cgroup_fork (p);
@@ -1130,7 +1119,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,if ((retval =security_task_alloc (p))) goto bad_fork_cleanup_policy;if ((retval =audit_alloc (p))) - goto bad_fork_cleanup_security; + goto bad_fork_cleanup_policy;/* copy all the process information */ if ((retval =copy_semundo (clone_flags, p))) goto bad_fork_cleanup_audit;
@@ -1144,10 +1133,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, goto bad_fork_cleanup_sighand;if ((retval =copy_mm (clone_flags, p))) goto bad_fork_cleanup_signal; -if ((retval =copy_keys (clone_flags, p))) - goto bad_fork_cleanup_mm;if ((retval =copy_namespaces (clone_flags, p))) - goto bad_fork_cleanup_keys; + goto bad_fork_cleanup_mm; retval =copy_thread (0 , clone_flags, stack_start, stack_size, p, regs);if (retval) goto bad_fork_cleanup_namespaces;
@@ -1320,8 +1307,6 @@ bad_fork_free_pid:free_pid (pid); bad_fork_cleanup_namespaces:exit_task_namespaces (p); -bad_fork_cleanup_keys: -exit_keys (p); bad_fork_cleanup_mm:if (p->mm)mmput (p->mm);
@@ -1337,8 +1322,6 @@ bad_fork_cleanup_semundo:exit_sem (p); bad_fork_cleanup_audit:audit_free (p); -bad_fork_cleanup_security: -security_task_free (p); bad_fork_cleanup_policy:#ifdef CONFIG_NUMA mpol_free (p->mempolicy);
@@ -1351,9 +1334,10 @@ bad_fork_cleanup_cgroup: bad_fork_cleanup_put_domain:module_put (task_thread_info (p)->exec_domain->module); bad_fork_cleanup_count: -put_group_info (p->sec->group_info);atomic_dec (&p->sec->user->processes); -free_uid (p->sec->user); +bad_fork_cleanup_put_task_sec: +put_task_security (p->act_as); +put_task_security (p->sec); bad_fork_free:free_task (p); fork_out:
kernel/kmod.c +4 -6
@@ -133,20 +133,18 @@ struct subprocess_info {static int ____call_usermodehelper (void *data) {struct subprocess_info *sub_info = data; -struct key *new_session, *old_session;int retval; -/* Unblock all signals and set the session keyring. */ - new_session =key_get (sub_info->ring); +/* Set the session keyring. */ +__install_session_keyring (current, sub_info->ring); + +/* Unblock all signals. */ spin_lock_irq (¤t->sighand->siglock); - old_session =__install_session_keyring (current, new_session);flush_signal_handlers (current,1 );sigemptyset (¤t->blocked);recalc_sigpending ();spin_unlock_irq (¤t->sighand->siglock); -key_put (old_session); -/* Install input pipe when needed */ if (sub_info->stdin) {struct files_struct *f = current->files;
kernel/sys.c +8 -8
@@ -521,7 +521,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) sec->fsgid = new_egid; sec->egid = new_egid; sec->gid = new_rgid; -key_fsgid_changed (current); +key_fsgid_changed (sec);proc_id_connector (current,PROC_EVENT_GID );return 0 ; }
@@ -557,7 +557,7 @@ asmlinkage long sys_setgid(gid_t gid)else return -EPERM ; -key_fsgid_changed (current); +key_fsgid_changed (sec);proc_id_connector (current,PROC_EVENT_GID );return 0 ; }
@@ -646,7 +646,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) sec->suid = sec->euid; sec->fsuid = sec->euid; -key_fsuid_changed (current); +key_fsuid_changed (sec);proc_id_connector (current,PROC_EVENT_UID );return security_task_post_setuid (old_ruid, old_euid, old_suid,LSM_SETID_RE );
@@ -694,7 +694,7 @@ asmlinkage long sys_setuid(uid_t uid) sec->fsuid = sec->euid = uid; sec->suid = new_suid; -key_fsuid_changed (current); +key_fsuid_changed (sec);proc_id_connector (current,PROC_EVENT_UID );return security_task_post_setuid (old_ruid, old_euid, old_suid,LSM_SETID_ID );
@@ -744,7 +744,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)if (suid != (uid_t) -1 ) sec->suid = suid; -key_fsuid_changed (current); +key_fsuid_changed (sec);proc_id_connector (current,PROC_EVENT_UID );return security_task_post_setuid (old_ruid, old_euid, old_suid,LSM_SETID_RES );
@@ -798,7 +798,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)if (sgid != (gid_t) -1 ) sec->sgid = sgid; -key_fsgid_changed (current); +key_fsgid_changed (sec);proc_id_connector (current,PROC_EVENT_GID );return 0 ; }
@@ -841,7 +841,7 @@ asmlinkage long sys_setfsuid(uid_t uid) sec->fsuid = uid; } -key_fsuid_changed (current); +key_fsuid_changed (sec);proc_id_connector (current,PROC_EVENT_UID );security_task_post_setuid (old_fsuid, (uid_t)-1 , (uid_t)-1 ,LSM_SETID_FS );
@@ -869,7 +869,7 @@ asmlinkage long sys_setfsgid(gid_t gid)smp_wmb (); } sec->fsgid = gid; -key_fsgid_changed (current); +key_fsgid_changed (sec);proc_id_connector (current,PROC_EVENT_GID ); }return old_fsgid;
kernel/user.c +1 -1
@@ -356,7 +356,7 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)#endif new->locked_shm =0 ; -if (alloc_uid_keyring (new, current) <0 ) { +if (alloc_uid_keyring (new, current->sec) <0 ) {kmem_cache_free (uid_cachep, new);uids_mutex_unlock ();return NULL ;
net/rxrpc/ar-key.c +2 -2
@@ -297,7 +297,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *conn,_enter ("" ); - key =key_alloc (&key_type_rxrpc,"x" ,0 ,0 , current,0 , + key =key_alloc (&key_type_rxrpc,"x" ,0 ,0 , current->act_as,0 ,KEY_ALLOC_NOT_IN_QUOTA );if (IS_ERR (key)) {_leave (" = -ENOMEM [alloc %ld]" ,PTR_ERR (key));
@@ -343,7 +343,7 @@ struct key *rxrpc_get_null_key(const char *keyname)struct key *key;int ret; - key =key_alloc (&key_type_rxrpc, keyname,0 ,0 , current, + key =key_alloc (&key_type_rxrpc, keyname,0 ,0 , current->act_as,KEY_POS_SEARCH ,KEY_ALLOC_NOT_IN_QUOTA );if (IS_ERR (key))return key;
security/dummy.c +10 -4
@@ -480,16 +480,21 @@ static int dummy_task_create (unsigned long clone_flags)return 0 ; } -static int dummy_task_alloc_security (struct task_struct *p) +static int dummy_task_alloc_security (struct task_struct *p) {return 0 ; } -static void dummy_task_free_security (struct task_struct *p) +static void dummy_task_free_security (struct task_security *sec) {return ; } +static int dummy_task_dup_security (struct task_security *p) +{ +return 0 ; +} +static int dummy_task_setuid (uid_t id0,uid_t id1,uid_t id2,int flags) {return 0 ;
@@ -943,7 +948,7 @@ static void dummy_release_secctx(char *secdata, u32 seclen) }#ifdef CONFIG_KEYS -static inline int dummy_key_alloc (struct key *key,struct task_struct *ctx, +static inline int dummy_key_alloc (struct key *key,struct task_security *sec,unsigned long flags) {return 0 ;
@@ -954,7 +959,7 @@ static inline void dummy_key_free(struct key *key) }static inline int dummy_key_permission (key_ref_t key_ref, -struct task_struct *context, +struct task_security *sec,key_perm_t perm) {return 0 ;
@@ -1057,6 +1062,7 @@ void security_fixup_ops (struct security_operations *ops)set_to_dummy_if_null (ops, task_create);set_to_dummy_if_null (ops, task_alloc_security);set_to_dummy_if_null (ops, task_free_security); +set_to_dummy_if_null (ops, task_dup_security);set_to_dummy_if_null (ops, task_setuid);set_to_dummy_if_null (ops, task_post_setuid);set_to_dummy_if_null (ops, task_setgid);
security/keys/internal.h +5 -5
@@ -92,7 +92,7 @@ extern struct key *keyring_search_instkey(struct key *keyring,typedef int (*key_match_func_t )(const struct key *,const void *);extern key_ref_t keyring_search_aux (key_ref_t keyring_ref, -struct task_struct *tsk, +struct task_security *sec,struct key_type *type,const void *description,key_match_func_t match);
@@ -100,12 +100,12 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,extern key_ref_t search_process_keyrings (struct key_type *type,const void *description,key_match_func_t match, -struct task_struct *tsk); +struct task_security *sec);extern struct key *find_keyring_by_name (const char *name,key_serial_t bound); -extern int install_thread_keyring (struct task_struct *tsk); -extern int install_process_keyring (struct task_struct *tsk); +extern int install_thread_keyring (struct task_security *sec); +extern int install_process_keyring (struct task_security *sec); extern struct key *request_key_and_link(struct key_type *type, const char *description,
@@ -120,7 +120,7 @@ extern struct key *request_key_and_link(struct key_type *type,*/ struct request_key_auth {struct key *target_key; -struct task_struct *context; +struct task_security *sec;void *callout_info;size_t callout_len;pid_t pid;
security/keys/key.c +3 -3
@@ -243,7 +243,7 @@ serial_exists:* instantiate the key or discard it before returning */ struct key *key_alloc (struct key_type *type,const char *desc, -uid_t uid,gid_t gid,struct task_struct *ctx, +uid_t uid,gid_t gid,struct task_security *sec,key_perm_t perm,unsigned long flags) {struct key_user *user =NULL ;
@@ -314,7 +314,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,#endif /* let the security module know about the key */ - ret =security_key_alloc (key, ctx, flags); + ret =security_key_alloc (key, sec, flags);if (ret <0 ) goto security_error;
@@ -818,7 +818,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,/* allocate a new key */ key =key_alloc (ktype, description,current_fsuid (),current_fsgid (), - current, perm, flags); + current->act_as, perm, flags);if (IS_ERR (key)) { key_ref =ERR_PTR (PTR_ERR (key)); goto error_3;
security/keys/keyctl.c +3 -3
@@ -878,7 +878,7 @@ long keyctl_instantiate_key(key_serial_t id,* requesting task */ keyring_ref =NULL ;if (ringid) { - keyring_ref =lookup_user_key (rka->context, ringid,1 ,0 , + keyring_ref =lookup_user_key (rka->sec, ringid,1 ,0 ,KEY_WRITE );if (IS_ERR (keyring_ref)) { ret =PTR_ERR (keyring_ref);
@@ -973,13 +973,13 @@ long keyctl_set_reqkey_keyring(int reqkey_defl)switch (reqkey_defl) {case KEY_REQKEY_DEFL_THREAD_KEYRING : - ret =install_thread_keyring (current); + ret =install_thread_keyring (sec);if (ret <0 )return ret; goto set;case KEY_REQKEY_DEFL_PROCESS_KEYRING : - ret =install_process_keyring (current); + ret =install_process_keyring (sec);if (ret <0 )return ret;
security/keys/keyring.c +7 -7
@@ -244,14 +244,14 @@ static long keyring_read(const struct key *keyring,* allocate a keyring and link into the destination keyring */ struct key *keyring_alloc (const char *description,uid_t uid,gid_t gid, -struct task_struct *ctx,unsigned long flags, +struct task_security *sec,unsigned long flags,struct key *dest) {struct key *keyring;int ret; keyring =key_alloc (&key_type_keyring, description, - uid, gid, ctx, + uid, gid, sec, (KEY_POS_ALL & ~KEY_POS_SETATTR ) |KEY_USR_ALL , flags);
@@ -280,7 +280,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,* - we propagate the possession attribute from the keyring ref to the key ref */ key_ref_t keyring_search_aux (key_ref_t keyring_ref, -struct task_struct *context, +struct task_security *sec,struct key_type *type,const void *description,key_match_func_t match)
@@ -303,7 +303,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,key_check (keyring);/* top keyring must have search permission to begin the search */ - err =key_task_permission (keyring_ref, context,KEY_SEARCH ); + err =key_task_permission (keyring_ref, sec,KEY_SEARCH );if (err <0 ) { key_ref =ERR_PTR (err); goto error;
@@ -376,7 +376,7 @@ descend:/* key must have search permissions */ if (key_task_permission (make_key_ref (key, possessed), - context,KEY_SEARCH ) <0 ) + sec,KEY_SEARCH ) <0 )continue ;/* we set a different error code if we pass a negative key */
@@ -403,7 +403,7 @@ ascend:continue ;if (key_task_permission (make_key_ref (key, possessed), - context,KEY_SEARCH ) <0 ) + sec,KEY_SEARCH ) <0 )continue ;/* stack the current position */
@@ -458,7 +458,7 @@ key_ref_t keyring_search(key_ref_t keyring,if (!type->match)return ERR_PTR (-ENOKEY ); -return keyring_search_aux (keyring, current, +return keyring_search_aux (keyring, current->sec, type, description, type->match); }/* end keyring_search() */
security/keys/permission.c +2 -3
@@ -19,10 +19,9 @@* but permit the security modules to override */ int key_task_permission (const key_ref_t key_ref, -struct task_struct *context, +struct task_security *sec,key_perm_t perm) { -struct task_security *sec = context->act_as;struct key *key;key_perm_t kperm;int ret;
@@ -69,7 +68,7 @@ use_these_perms:return -EACCES ;/* let LSM be the final arbiter */ -return security_key_permission (key_ref, context, perm); +return security_key_permission (key_ref, sec, perm); }/* end key_task_permission() */
security/keys/proc.c +1 -1
@@ -141,7 +141,7 @@ static int proc_keys_show(struct seq_file *m, void *v)/* check whether the current task is allowed to view the key (assuming * non-possession) */ - rc =key_task_permission (make_key_ref (key,0 ), current,KEY_VIEW ); + rc =key_task_permission (make_key_ref (key,0 ), current->sec,KEY_VIEW );if (rc <0 )return 0 ;
security/keys/process_keys.c +133 -157
585 lines not on this page · raw message
security/keys/request_key.c +28 -31
174 lines not on this page · raw message
security/keys/request_key_auth.c +15 -23
@@ -104,10 +104,8 @@ static void request_key_auth_revoke(struct key *key)kenter ("{%d}" , key->serial); -if (rka->context) { -put_task_struct (rka->context); - rka->context =NULL ; - } +put_task_security (rka->sec); + rka->sec =NULL ; }/* end request_key_auth_revoke() */
@@ -121,11 +119,7 @@ static void request_key_auth_destroy(struct key *key)kenter ("{%d}" , key->serial); -if (rka->context) { -put_task_struct (rka->context); - rka->context =NULL ; - } - +put_task_security (rka->sec);key_put (rka->target_key);kfree (rka->callout_info);kfree (rka);
@@ -141,6 +135,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info, size_t callout_len) {struct request_key_auth *rka, *irka; +struct task_security *sec = current->sec;struct key *authkey =NULL ;char desc[20 ];int ret;
@@ -162,28 +157,25 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,/* see if the calling process is already servicing the key request of * another process */ -if (current->act_as->request_key_auth) { +if (sec->request_key_auth) {/* it is - use that instantiation context here too */ -down_read (¤t->act_as->request_key_auth->sem); +down_read (&sec->request_key_auth->sem);/* if the auth key has been revoked, then the key we're * servicing is already instantiated */ -if (test_bit (KEY_FLAG_REVOKED , - ¤t->act_as->request_key_auth->flags)) +if (test_bit (KEY_FLAG_REVOKED , &sec->request_key_auth->flags)) goto auth_key_revoked; - irka = current->act_as->request_key_auth->payload.data; - rka->context = irka->context; + irka = sec->request_key_auth->payload.data; + rka->sec = irka->sec; rka->pid = irka->pid; -get_task_struct (rka->context); +get_task_security (rka->sec); -up_read (¤t->act_as->request_key_auth->sem); - } -else { +up_read (&sec->request_key_auth->sem); + }else {/* it isn't - use this process as the context */ - rka->context = current; + rka->sec =get_task_security (sec); rka->pid = current->pid; -get_task_struct (rka->context); } rka->target_key =key_get (target);
@@ -194,7 +186,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,sprintf (desc,"%x" , target->serial); authkey =key_alloc (&key_type_request_key_auth, desc, -current_fsuid (),current_fsgid (), current, + sec->fsuid, sec->fsgid, sec,KEY_POS_VIEW |KEY_POS_READ |KEY_POS_SEARCH |KEY_USR_VIEW ,KEY_ALLOC_NOT_IN_QUOTA );if (IS_ERR (authkey)) {
@@ -260,7 +252,7 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id) &key_type_request_key_auth, (void *) (unsigned long ) target_id, key_get_instantiation_authkey_match, - current); + current->act_as);if (IS_ERR (authkey_ref)) { authkey =ERR_PTR (PTR_ERR (authkey_ref));
security/security.c +13 -7
@@ -573,9 +573,14 @@ int security_task_alloc(struct task_struct *p)return security_ops->task_alloc_security (p); } -void security_task_free (struct task_struct *p) +void security_task_free (struct task_security *sec) { - security_ops->task_free_security (p); + security_ops->task_free_security (sec); +} + +int security_task_dup (struct task_security *sec) +{ +return security_ops->task_dup_security (sec); }int security_task_setuid (uid_t id0,uid_t id1,uid_t id2,int flags)
@@ -1063,9 +1068,10 @@ EXPORT_SYMBOL(security_skb_classify_flow);#ifdef CONFIG_KEYS -int security_key_alloc (struct key *key,struct task_struct *tsk,unsigned long flags) +int security_key_alloc (struct key *key,struct task_security *sec, +unsigned long flags) { -return security_ops->key_alloc (key, tsk, flags); +return security_ops->key_alloc (key, sec, flags); }void security_key_free (struct key *key)
@@ -1073,10 +1079,10 @@ void security_key_free(struct key *key) security_ops->key_free (key); } -int security_key_permission (key_ref_t key_ref, -struct task_struct *context,key_perm_t perm) +int security_key_permission (key_ref_t key_ref,struct task_security *sec, +key_perm_t perm) { -return security_ops->key_permission (key_ref, context, perm); +return security_ops->key_permission (key_ref, sec, perm); }int security_key_getsecurity (struct key *key,char **_buffer)
security/selinux/hooks.c +35 -11
93 lines not on this page · raw message
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 8/26 Add a secctx_to_secid() LSM hook to go along with the existing
In reply to David Howellssecid_to_secctx() LSM hook. This patch also includes the SELinux implementation for this hook.
---
include/linux/security.h | 13 +++++++++++++ security/dummy.c | 6 ++++++ security/security.c | 6 ++++++ security/selinux/hooks.c | 6 ++++++ 4 files changed, 31 insertions(+), 0 deletions(-)
include/linux/security.h +13 -0
@@ -1200,6 +1200,10 @@ struct request_sock;* Convert secid to security context. * @secid contains the security ID. * @secdata contains the pointer that stores the converted security context. +* @secctx_to_secid: +* Convert security context to secid. +* @secid contains the pointer to the generated security ID. +* @secdata contains the security context. * * @release_secctx: * Release the security context.
@@ -1389,6 +1393,7 @@ struct security_operations {int (*getprocattr)(struct task_struct *p,char *name,char **value);int (*setprocattr)(struct task_struct *p,char *name,void *value,size_t size);int (*secid_to_secctx)(u32 secid,char **secdata,u32 *seclen); +int (*secctx_to_secid)(char *secdata,u32 seclen,u32 *secid);void (*release_secctx)(char *secdata,u32 seclen);#ifdef CONFIG_SECURITY_NETWORK
@@ -1623,6 +1628,7 @@ int security_setprocattr(struct task_struct *p, char *name, void *value, size_tint security_netlink_send (struct sock *sk,struct sk_buff *skb);int security_netlink_recv (struct sk_buff *skb,int cap);int security_secid_to_secctx (u32 secid,char **secdata,u32 *seclen); +int security_secctx_to_secid (char *secdata,u32 seclen,u32 *secid);void security_release_secctx (char *secdata,u32 seclen);#else /* CONFIG_SECURITY */
@@ -2305,6 +2311,13 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclereturn -EOPNOTSUPP ; } +static inline int security_secctx_to_secid (char *secdata, +u32 seclen, +u32 *secid) +{ +return -EOPNOTSUPP ; +} +static inline void security_release_secctx (char *secdata,u32 seclen) { }
security/dummy.c +6 -0
@@ -943,6 +943,11 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)return -EOPNOTSUPP ; } +static int dummy_secctx_to_secid (char *secdata,u32 seclen,u32 *secid) +{ +return -EOPNOTSUPP ; +} +static void dummy_release_secctx (char *secdata,u32 seclen) { }
@@ -1109,6 +1114,7 @@ void security_fixup_ops (struct security_operations *ops)set_to_dummy_if_null (ops, getprocattr);set_to_dummy_if_null (ops, setprocattr);set_to_dummy_if_null (ops, secid_to_secctx); +set_to_dummy_if_null (ops, secctx_to_secid);set_to_dummy_if_null (ops, release_secctx);#ifdef CONFIG_SECURITY_NETWORK set_to_dummy_if_null (ops, unix_stream_connect);
security/security.c +6 -0
@@ -821,6 +821,12 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) }EXPORT_SYMBOL (security_secid_to_secctx); +int security_secctx_to_secid (char *secdata,u32 seclen,u32 *secid) +{ +return security_ops->secctx_to_secid (secdata, seclen, secid); +} +EXPORT_SYMBOL (security_secctx_to_secid); +void security_release_secctx (char *secdata,u32 seclen) {return security_ops->release_secctx (secdata, seclen);
security/selinux/hooks.c +6 -0
@@ -4734,6 +4734,11 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)return security_sid_to_context (secid, secdata, seclen); } +static int selinux_secctx_to_secid (char *secdata,u32 seclen,u32 *secid) +{ +return security_context_to_sid (secdata, seclen, secid); +} +static void selinux_release_secctx (char *secdata,u32 seclen) {kfree (secdata);
@@ -4937,6 +4942,7 @@ static struct security_operations selinux_ops = { .setprocattr = selinux_setprocattr, .secid_to_secctx = selinux_secid_to_secctx, + .secctx_to_secid = selinux_secctx_to_secid, .release_secctx = selinux_release_secctx, .unix_stream_connect = selinux_socket_unix_stream_connect,
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
James Morris
maintainerRe: [PATCH 08/26] Add a secctx_to_secid() LSM hook to go along with the existing
Quoted 5 lines · David Howells
secid_to_secctx()LSM hook. This patch also includes the SELinux implementation for this hook.Signed-off-by Paul Moore <[email protected]>Acked-by Stephen Smalley <[email protected]>
This is useful in its own right, and I would like to push it upstream for 2.6.24 unless there are any objections.
Quoted 125 lines
---
include/linux/security.h | 13 +++++++++++++ security/dummy.c | 6 ++++++ security/security.c | 6 ++++++ security/selinux/hooks.c | 6 ++++++ 4 files changed, 31 insertions(+), 0 deletions(-)include/linux/security.h +13
-0@@ -1200,6 +1200,10 @@ struct request_sock;* Convert secid to security context. * @secid contains the security ID. * @secdata contains the pointer that stores the converted security context. +* @secctx_to_secid: +* Convert security context to secid. +* @secid contains the pointer to the generated security ID. +* @secdata contains the security context. * * @release_secctx: * Release the security context. @@ -1389,6 +1393,7 @@ struct security_operations {int (*getprocattr)(struct task_struct *p,char *name,char **value);int (*setprocattr)(struct task_struct *p,char *name,void *value,size_t size);int (*secid_to_secctx)(u32 secid,char **secdata,u32 *seclen); +int (*secctx_to_secid)(char *secdata,u32 seclen,u32 *secid);void (*release_secctx)(char *secdata,u32 seclen);#ifdef CONFIG_SECURITY_NETWORK @@ -1623,6 +1628,7 @@ int security_setprocattr(struct task_struct *p, char *name, void *value, size_tint security_netlink_send (struct sock *sk,struct sk_buff *skb);int security_netlink_recv (struct sk_buff *skb,int cap);int security_secid_to_secctx (u32 secid,char **secdata,u32 *seclen); +int security_secctx_to_secid (char *secdata,u32 seclen,u32 *secid);void security_release_secctx (char *secdata,u32 seclen);#else /* CONFIG_SECURITY */ @@ -2305,6 +2311,13 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclereturn -EOPNOTSUPP ; } +static inline int security_secctx_to_secid (char *secdata, +u32 seclen, +u32 *secid) +{ +return -EOPNOTSUPP ; +} +static inline void security_release_secctx (char *secdata,u32 seclen) { }security/dummy.c +6
-0@@ -943,6 +943,11 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)return -EOPNOTSUPP ; } +static int dummy_secctx_to_secid (char *secdata,u32 seclen,u32 *secid) +{ +return -EOPNOTSUPP ; +} +static void dummy_release_secctx (char *secdata,u32 seclen) { }@@ -1109,6 +1114,7 @@ void security_fixup_ops (struct security_operations *ops)set_to_dummy_if_null (ops, getprocattr);set_to_dummy_if_null (ops, setprocattr);set_to_dummy_if_null (ops, secid_to_secctx); +set_to_dummy_if_null (ops, secctx_to_secid);set_to_dummy_if_null (ops, release_secctx);#ifdef CONFIG_SECURITY_NETWORK set_to_dummy_if_null (ops, unix_stream_connect);security/security.c +6
-0@@ -821,6 +821,12 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) }EXPORT_SYMBOL (security_secid_to_secctx); +int security_secctx_to_secid (char *secdata,u32 seclen,u32 *secid) +{ +return security_ops->secctx_to_secid (secdata, seclen, secid); +} +EXPORT_SYMBOL (security_secctx_to_secid); +void security_release_secctx (char *secdata,u32 seclen) {return security_ops->release_secctx (secdata, seclen);security/selinux/hooks.c +6
-1@@ -4734,6 +4734,11 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)return security_sid_to_context (secid, secdata, seclen); } +static int selinux_secctx_to_secid (char *secdata,u32 seclen,u32 *secid) +{ +return security_context_to_sid (secdata, seclen, secid); +} +static void selinux_release_secctx (char *secdata,u32 seclen) {kfree (secdata);@@ -4937,6 +4942,7 @@ static struct security_operations selinux_ops = { .setprocattr = selinux_setprocattr, .secid_to_secctx = selinux_secid_to_secctx, + .secctx_to_secid = selinux_secctx_to_secid, .release_secctx = selinux_release_secctx, .unix_stream_connect = selinux_socket_unix_stream_connect, -To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 7 lines
James Morris <[email protected]> -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Re: [PATCH 08/26] Add a secctx_to_secid() LSM hook to go along with the existing
Quoted 9 lines · James Morris
Quoted 5 lines · David Howells
secid_to_secctx()LSM hook. This patch also includes the SELinux implementation for this hook.Signed-off-by Paul Moore <[email protected]>Acked-by Stephen Smalley <[email protected]>This is useful in its own right, and I would like to push it upstream for 2.6.24 unless there are any objections.
Isn't it a bit late in 2.6.24 to add new functionality, especially when there isn't an in-tree user for it in 2.6.24?
You are right, there are several users of this function currently under development but I'm pretty sure all of them are targeting 2.6.25 or greater. With that in mind, I think the prudent thing to is to wait and push this upstream for 2.6.25.
Signature · 7 lines
paul moore linux security @ hp -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Re: [PATCH 08/26] Add a secctx_to_secid() LSM hook to go along with the existing
Quoted 13 lines · --- Paul Moore
Quoted 9 lines · James Morris
Quoted 5 lines · David Howells
secid_to_secctx()LSM hook. This patch also includes the SELinux implementation for this hook.Signed-off-by Paul Moore <[email protected]>Acked-by Stephen Smalley <[email protected]>This is useful in its own right, and I would like to push it upstream for 2.6.24 unless there are any objections.
Isn't it a bit late in 2.6.24 to add new functionality, especially when there
Quoted 7 lines
isn't an in-tree user for it in 2.6.24?
You are right, there are several users of this function currently under development but I'm pretty sure all of them are targeting 2.6.25 or greater.
With that in mind, I think the prudent thing to is to wait and push this upstream for 2.6.25.
I concur with Paul. I had to delete the message I was composing because it said exactly the same thing.
I do think that we need to put some thought into what a secid really is and what a secctx ought to look like what with multiple user cropping up for them. To date audit is the only out-of-LSM user of the secctx, and assumes it's a printable text string, but if cacheing is going to be using it as well we're approaching the secctx being a "general" interface, and hence a part of the LSM proper. Probably makes sense to include something in the LSM documentation. With luck, someone who spells better than I will beat me to it, but such an update is on my todo list.
Casey Schaufler
[email protected]
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
James Morris
maintainerRe: [PATCH 08/26] Add a secctx_to_secid() LSM hook to go along with the existing
In reply to Paul MooreQuoted 5 lines · Paul Moore
Quoted 4 lines · James Morris
Quoted 3 lines · David Howells
secid_to_secctx()LSM hook. This patch also includes the SELinux implementation for this hook.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
Signed-off-by Paul Moore <[email protected]>Acked-by Stephen Smalley <[email protected]>This is useful in its own right, and I would like to push it upstream for 2.6.24 unless there are any objections.
Isn't it a bit late in 2.6.24 to add new functionality, especially when there isn't an in-tree user for it in 2.6.24?
Actually, I meant to go into 2.6.24 after the merge window opens.
Quoted 5 lines
You are right, there are several users of this function currently under development but I'm pretty sure all of them are targeting 2.6.25 or greater. With that in mind, I think the prudent thing to is to wait and push this upstream for 2.6.25.
Signature · 7 lines
James Morris <[email protected]> -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Re: [PATCH 08/26] Add a secctx_to_secid() LSM hook to go along with the existing
Quoted 9 lines · James Morris
Quoted 8 lines · Paul Moore
Quoted 7 lines · James Morris
Quoted 5 lines · David Howells
secid_to_secctx()LSM hook. This patch also includes the SELinux implementation for this hook.Signed-off-by Paul Moore <[email protected]>Acked-by Stephen Smalley <[email protected]>
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
This is useful in its own right, and I would like to push it upstream for 2.6.24 unless there are any objections.
Isn't it a bit late in 2.6.24 to add new functionality, especially when there isn't an in-tree user for it in 2.6.24?
Actually, I meant to go into 2.6.24 after the merge window opens.
I'm assuming you meant 2.6.25 in the sentence above?
Signature · 7 lines
paul moore linux security @ hp -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 9/26 Security: Pre-add additional non-caching classes
In reply to David HowellsPre-add additional non-caching classes that are in the SELinux upstream repository, but not in the upstream kernel so they don't get in the fscache class patch.
---
security/selinux/include/av_perm_to_string.h | 5 +++++ security/selinux/include/av_permissions.h | 5 +++++ security/selinux/include/class_to_string.h | 7 +++++++ security/selinux/include/flask.h | 1 + 4 files changed, 18 insertions(+), 0 deletions(-)
security/selinux/include/av_perm_to_string.h +5 -0
@@ -37,6 +37,8 @@ S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest") S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv") S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send") + S_(SECCLASS_NODE, NODE__RECVFROM, "recvfrom") + S_(SECCLASS_NODE, NODE__SENDTO, "sendto") S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv") S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send")S_ (SECCLASS_NETIF ,NETIF__UDP_RECV ,"udp_recv" )
@@ -45,6 +47,8 @@ S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send") S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv") S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send") + S_(SECCLASS_NETIF, NETIF__INGRESS, "ingress") + S_(SECCLASS_NETIF, NETIF__EGRESS, "egress") S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto") S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn")S_ (SECCLASS_UNIX_STREAM_SOCKET ,UNIX_STREAM_SOCKET__ACCEPTFROM ,"acceptfrom" )
@@ -159,3 +163,4 @@ S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero") +S_ (SECCLASS_PEER ,PEER__RECV ,"recv" )
security/selinux/include/av_permissions.h +5 -0
@@ -292,6 +292,8 @@#define NODE__ENFORCE_DEST 0x00000040UL#define NODE__DCCP_RECV 0x00000080UL#define NODE__DCCP_SEND 0x00000100UL +#define NODE__RECVFROM 0x00000200UL +#define NODE__SENDTO 0x00000400UL#define NETIF__TCP_RECV 0x00000001UL#define NETIF__TCP_SEND 0x00000002UL#define NETIF__UDP_RECV 0x00000004UL
@@ -300,6 +302,8 @@#define NETIF__RAWIP_SEND 0x00000020UL#define NETIF__DCCP_RECV 0x00000040UL#define NETIF__DCCP_SEND 0x00000080UL +#define NETIF__INGRESS 0x00000100UL +#define NETIF__EGRESS 0x00000200UL#define NETLINK_SOCKET__IOCTL 0x00000001UL#define NETLINK_SOCKET__READ 0x00000002UL#define NETLINK_SOCKET__WRITE 0x00000004UL
@@ -824,3 +828,4 @@#define DCCP_SOCKET__NODE_BIND 0x00400000UL#define DCCP_SOCKET__NAME_CONNECT 0x00800000UL#define MEMPROTECT__MMAP_ZERO 0x00000001UL +#define PEER__RECV 0x00000001UL
security/selinux/include/class_to_string.h +7 -0
@@ -64,3 +64,10 @@ S_(NULL) S_("dccp_socket") S_("memprotect") + S_(NULL) + S_(NULL) + S_(NULL) + S_(NULL) + S_(NULL) + S_(NULL) + S_("peer")
security/selinux/include/flask.h +1 -0
@@ -50,6 +50,7 @@#define SECCLASS_KEY 58#define SECCLASS_DCCP_SOCKET 60#define SECCLASS_MEMPROTECT 61 +#define SECCLASS_PEER 68/* * Security identifier indices for initial entities
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 10/26 Security: Add a kernel_service object class to SELinux
In reply to David HowellsAdd a 'kernel_service' object class to SELinux and give this object class two access vectors: 'use_as_override' and 'create_files_as'.
The first vector is used to grant a process the right to nominate an alternate process security ID for the kernel to use as an override for the SELinux subjective security when accessing stuff on behalf of another process.
For example, CacheFiles when accessing the cache on behalf on a process accessing an NFS file needs to use a subjective security ID appropriate to the cache rather then the one the calling process is using. The cachefilesd daemon will nominate the security ID to be used.
The second vector is used to grant a process the right to nominate a file creation label for a kernel service to use.
---
security/selinux/include/av_perm_to_string.h | 2 ++ security/selinux/include/av_permissions.h | 2 ++ security/selinux/include/class_to_string.h | 1 + security/selinux/include/flask.h | 1 + 4 files changed, 6 insertions(+), 0 deletions(-)
security/selinux/include/av_perm_to_string.h +2 -0
@@ -164,3 +164,5 @@ S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero") S_(SECCLASS_PEER, PEER__RECV, "recv") + S_(SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__USE_AS_OVERRIDE, "use_as_override") +S_ (SECCLASS_KERNEL_SERVICE ,KERNEL_SERVICE__CREATE_FILES_AS ,"create_files_as" )
security/selinux/include/av_permissions.h +2 -0
@@ -829,3 +829,5 @@#define DCCP_SOCKET__NAME_CONNECT 0x00800000UL#define MEMPROTECT__MMAP_ZERO 0x00000001UL#define PEER__RECV 0x00000001UL +#define KERNEL_SERVICE__USE_AS_OVERRIDE 0x00000001UL +#define KERNEL_SERVICE__CREATE_FILES_AS 0x00000002UL
security/selinux/include/class_to_string.h +1 -0
@@ -71,3 +71,4 @@ S_(NULL) S_(NULL) S_("peer") +S_ ("kernel_service" )
security/selinux/include/flask.h +1 -0
@@ -51,6 +51,7 @@#define SECCLASS_DCCP_SOCKET 60#define SECCLASS_MEMPROTECT 61#define SECCLASS_PEER 68 +#define SECCLASS_KERNEL_SERVICE 69/* * Security identifier indices for initial entities
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 11/26 Security: Allow kernel services to override LSM settings for task actions
In reply to David HowellsAllow kernel services to override LSM settings appropriate to the actions performed by a task by duplicating a security record, modifying it and then using task_struct::act_as to point to it when performing operations on behalf of a task.
This is used, for example, by CacheFiles which has to transparently access the cache on behalf of a process that thinks it is doing, say, NFS accesses with a potentially inappropriate (with respect to accessing the cache) set of security data.
This patch provides two LSM hooks for modifying a task security record:
(*) security_kernel_act_as() which allows modification of the security datum
with which a task acts on other objects (most notably files).
(*) security_create_files_as() which allows modification of the security
datum that is used to initialise the security data on a file that a task creates.
---
include/linux/cred.h | 23 +++++++ include/linux/security.h | 42 ++++++++++++- kernel/cred.c | 111 +++++++++++++++++++++++++++++++++++ security/dummy.c | 17 +++++ security/security.c | 15 ++++- security/selinux/hooks.c | 51 ++++++++++++++++ security/selinux/include/security.h | 2 - security/selinux/ss/services.c | 5 +- 8 files changed, 257 insertions(+), 9 deletions(-) create mode 100644 include/linux/cred.h
include/linux/cred.h new file +23 -0
@@ -0,0 +1,23 @@ +/* Credential management +* +* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. +* Written by David Howells ([email protected]) +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public Licence +* as published by the Free Software Foundation; either version +* 2 of the Licence, or (at your option) any later version. +*/ + +#ifndef _LINUX_CRED_H +#define _LINUX_CRED_H + +struct task_security ; +struct inode ; + +extern struct task_security *get_kernel_security (struct task_struct *); +extern int set_security_override (struct task_security *,u32 ); +extern int set_security_override_from_ctx (struct task_security *,const char *); +extern int change_create_files_as (struct task_security *,struct inode *); + +#endif /* _LINUX_CRED_H */
include/linux/security.h +39 -3
84 lines not on this page · raw message
kernel/cred.c +111 -0
120 lines not on this page · raw message
security/dummy.c +16 -1
@@ -495,6 +495,19 @@ static int dummy_task_dup_security(struct task_security *p)return 0 ; } +static int dummy_task_kernel_act_as (struct task_struct *p, +struct task_security *sec,u32 secid) +{ +return 0 ; +} + +static int dummy_task_create_files_as (struct task_struct *p, +struct task_security *sec, +struct inode *inode) +{ +return 0 ; +} +static int dummy_task_setuid (uid_t id0,uid_t id1,uid_t id2,int flags) {return 0 ;
@@ -943,7 +956,7 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)return -EOPNOTSUPP ; } -static int dummy_secctx_to_secid (char *secdata,u32 seclen,u32 *secid) +static int dummy_secctx_to_secid (const char *secdata,u32 seclen,u32 *secid) {return -EOPNOTSUPP ; }
@@ -1068,6 +1081,8 @@ void security_fixup_ops (struct security_operations *ops)set_to_dummy_if_null (ops, task_alloc_security);set_to_dummy_if_null (ops, task_free_security);set_to_dummy_if_null (ops, task_dup_security); +set_to_dummy_if_null (ops, task_kernel_act_as); +set_to_dummy_if_null (ops, task_create_files_as);set_to_dummy_if_null (ops, task_setuid);set_to_dummy_if_null (ops, task_post_setuid);set_to_dummy_if_null (ops, task_setgid);
security/security.c +14 -1
@@ -583,6 +583,19 @@ int security_task_dup(struct task_security *sec)return security_ops->task_dup_security (sec); } +int security_task_kernel_act_as (struct task_struct *p, +struct task_security *sec,u32 secid) +{ +return security_ops->task_kernel_act_as (p, sec, secid); +} + +int security_task_create_files_as (struct task_struct *p, +struct task_security *sec, +struct inode *inode) +{ +return security_ops->task_create_files_as (p, sec, inode); +} +int security_task_setuid (uid_t id0,uid_t id1,uid_t id2,int flags) {return security_ops->task_setuid (id0, id1, id2, flags);
@@ -821,7 +834,7 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) }EXPORT_SYMBOL (security_secid_to_secctx); -int security_secctx_to_secid (char *secdata,u32 seclen,u32 *secid) +int security_secctx_to_secid (const char *secdata,u32 seclen,u32 *secid) {return security_ops->secctx_to_secid (secdata, seclen, secid); }
security/selinux/hooks.c +50 -1
69 lines not on this page · raw message
security/selinux/include/security.h +1 -1
@@ -66,7 +66,7 @@ int security_change_sid(u32 ssid, u32 tsid,int security_sid_to_context (u32 sid,char **scontext,u32 *scontext_len); -int security_context_to_sid (char *scontext,u32 scontext_len, +int security_context_to_sid (const char *scontext,u32 scontext_len,u32 *out_sid);int security_context_to_sid_default (char *scontext,u32 scontext_len,u32 *out_sid,u32 def_sid);
security/selinux/ss/services.c +3 -2
@@ -677,7 +677,8 @@ out: } -static int security_context_to_sid_core (char *scontext,u32 scontext_len,u32 *sid,u32 def_sid) +static int security_context_to_sid_core (const char *scontext,u32 scontext_len, +u32 *sid,u32 def_sid) {char *scontext2;struct context context;
@@ -803,7 +804,7 @@ out:* Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient * memory is available, or 0 on success. */ -int security_context_to_sid (char *scontext,u32 scontext_len,u32 *sid) +int security_context_to_sid (const char *scontext,u32 scontext_len,u32 *sid) {return security_context_to_sid_core (scontext, scontext_len, sid,SECSID_NULL );
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 12/26 FS-Cache: Release page->private after failed readahead
In reply to David HowellsThe attached patch causes read_cache_pages() to release page-private data on a page for which add_to_page_cache() fails or the filler function fails. This permits pages with caching references associated with them to be cleaned up.
The invalidatepage() address space op is called (indirectly) to do the honours.
---
mm/readahead.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 files changed, 37 insertions(+), 2 deletions(-)
mm/readahead.c +37 -2
@@ -44,6 +44,41 @@ EXPORT_SYMBOL_GPL(file_ra_state_init);#define list_to_page (head) (list_entry((head)->prev, struct page, lru)) +/* +* see if a page needs releasing upon read_cache_pages() failure +* - the caller of read_cache_pages() may have set PG_private before calling, +* such as the NFS fs marking pages that are cached locally on disk, thus we +* need to give the fs a chance to clean up in the event of an error +*/ +static void read_cache_pages_invalidate_page (struct address_space *mapping, +struct page *page) +{ +if (PagePrivate (page)) { +if (TestSetPageLocked (page)) +BUG (); + page->mapping = mapping; +do_invalidatepage (page,0 ); + page->mapping =NULL ; +unlock_page (page); + } +page_cache_release (page); +} + +/* +* release a list of pages, invalidating them first if need be +*/ +static void read_cache_pages_invalidate_pages (struct address_space *mapping, +struct list_head *pages) +{ +struct page *victim; + +while (!list_empty (pages)) { + victim =list_to_page (pages); +list_del (&victim->lru); +read_cache_pages_invalidate_page (mapping, victim); + } +} +/** * read_cache_pages - populate an address space with some pages & start reads against them * @mapping: the address_space
@@ -65,14 +100,14 @@ int read_cache_pages(struct address_space *mapping, struct list_head *pages,list_del (&page->lru);if (add_to_page_cache_lru (page, mapping, page->index,GFP_KERNEL )) { -page_cache_release (page); +read_cache_pages_invalidate_page (mapping, page);continue ; }page_cache_release (page); ret =filler (data, page);if (unlikely (ret)) { -put_pages_list (pages); +read_cache_pages_invalidate_pages (mapping, pages);break ; }task_io_account_read (PAGE_CACHE_SIZE );
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 13/26 FS-Cache: Recruit a couple of page flags for cache management
In reply to David HowellsRecruit a couple of page flags to aid in cache management. The following extra flags are defined:
(1) PG_fscache (PG_private_2)
The marked page is backed by a local cache and is pinning resources in the cache driver.
(2) PG_fscache_write (PG_owner_priv_2)
The marked page is being written to the local cache. The page may not be modified whilst this is in progress.
If PG_fscache is set, then things that checked for PG_private will now also check for that. This includes things like truncation and page invalidation. The function page_has_private() had been added to make the checks for both PG_private and PG_private_2 at the same time.
---
fs/splice.c | 2 +- include/linux/page-flags.h | 40 ++++++++++++++++++++++++++++++++++++++-- include/linux/pagemap.h | 11 +++++++++++ mm/filemap.c | 16 ++++++++++++++++ mm/migrate.c | 2 +- mm/page_alloc.c | 3 +++ mm/readahead.c | 9 +++++---- mm/swap.c | 4 ++-- mm/swap_state.c | 4 ++-- mm/truncate.c | 10 +++++----- mm/vmscan.c | 2 +- 11 files changed, 85 insertions(+), 18 deletions(-)
fs/splice.c +1 -1
@@ -58,7 +58,7 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe,*/ wait_on_page_writeback (page); -if (PagePrivate (page)) +if (page_has_private (page))try_to_release_page (page,GFP_KERNEL );/*
include/linux/page-flags.h +38 -2
@@ -77,25 +77,32 @@#define PG_active 6#define PG_slab 7/* slab debug (Suparna wants this) */ -#define PG_owner_priv_1 8/* Owner use. If pagecache, fs may use*/ +#define PG_owner_priv_1 8/* Owner use. fs may use in pagecache */ #define PG_arch_1 9#define PG_reserved 10#define PG_private 11/* If pagecache, has fs-private data */ #define PG_writeback 12/* Page is under writeback */ +#define PG_private_2 13/* If pagecache, has fs aux data */ #define PG_compound 14/* Part of a compound page */ #define PG_swapcache 15/* Swap page: swp_entry_t in private */ #define PG_mappedtodisk 16/* Has blocks allocated on-disk */ #define PG_reclaim 17/* To be reclaimed asap */ +#define PG_owner_priv_2 18/* Owner use. fs may use in pagecache */ #define PG_buddy 19/* Page is free, on buddy lists */ /* PG_readahead is only used for file reads; PG_reclaim is only for writes */ #define PG_readahead PG_reclaim/* Reminder to do async read-ahead */ -/* PG_owner_priv_1 users should have descriptive aliases */ +/* PG_owner_priv_1/2 users should have descriptive aliases */ #define PG_checked PG_owner_priv_1/* Used by some filesystems */ #define PG_pinned PG_owner_priv_1/* Xen pinned pagetable */ +#define PG_fscache_write PG_owner_priv_2/* Writing to local cache */ + +/* PG_private_2 causes releasepage() and co to be invoked */ +#define PG_fscache PG_private_2/* Backed by local cache */ +#if (BITS_PER_LONG >32 )/*
@@ -199,6 +206,24 @@ static inline void SetPageUptodate(struct page *page)#define TestClearPageWriteback (page) test_and_clear_bit(PG_writeback, \ &(page)->flags) +#define PageFsCache (page) test_bit(PG_fscache, &(page)->flags) +#define SetPageFsCache (page) set_bit(PG_fscache, &(page)->flags) +#define ClearPageFsCache (page) clear_bit(PG_fscache, &(page)->flags) +#define TestSetPageFsCache (page) test_and_set_bit(PG_fscache, &(page)->flags) +#define TestClearPageFsCache (page) test_and_clear_bit(PG_fscache, \ + &(page)->flags) + +#define PageFsCacheWrite (page) test_bit(PG_fscache_write, \ + &(page)->flags) +#define SetPageFsCacheWrite (page) set_bit(PG_fscache_write, \ + &(page)->flags) +#define ClearPageFsCacheWrite (page) clear_bit(PG_fscache_write, \ + &(page)->flags) +#define TestSetPageFsCacheWrite (page) test_and_set_bit(PG_fscache_write, \ + &(page)->flags) +#define TestClearPageFsCacheWrite (page) test_and_clear_bit(PG_fscache_write, \ + &(page)->flags) +#define PageBuddy (page) test_bit(PG_buddy, &(page)->flags)#define __SetPageBuddy (page) __set_bit(PG_buddy, &(page)->flags)#define __ClearPageBuddy (page) __clear_bit(PG_buddy, &(page)->flags)
@@ -272,4 +297,15 @@ static inline void set_page_writeback(struct page *page) test_set_page_writeback(page); } +/** +* page_has_private - Determine if page has private stuff +* @page: The page to be checked +* +* Determine if a page has private stuff, indicating that release routines +* should be invoked upon it. +*/ +#define page_has_private (page) \ + ((page)->flags & ((1 << PG_private) | \ + (1 << PG_private_2))) +#endif /* PAGE_FLAGS_H */
include/linux/pagemap.h +11 -0
@@ -212,6 +212,17 @@ static inline void wait_on_page_writeback(struct page *page)extern void end_page_writeback (struct page *page);/* +* Wait for a page to finish being written to a local cache +*/ +static inline void wait_on_page_fscache_write (struct page *page) +{ +if (PageFsCacheWrite (page)) +wait_on_page_bit (page, PG_fscache_write); +} + +extern void end_page_fscache_write (struct page *page); + +/* * Fault a userspace page into pagetables. Return non-zero on a fault. * * This assumes that two userspace pages are always sufficient. That's
mm/filemap.c +16 -0
@@ -572,6 +572,19 @@ void end_page_writeback(struct page *page)EXPORT_SYMBOL (end_page_writeback);/** +* end_page_fscache_write - End writing page to cache +* @page: the page +*/ +void end_page_fscache_write (struct page *page) +{ +if (!TestClearPageFsCacheWrite (page)) +BUG (); +smp_mb__after_clear_bit (); +wake_up_page (page, PG_fscache_write); +} +EXPORT_SYMBOL (end_page_fscache_write); + +/** * __lock_page - get a lock on the page, assuming we need to sleep to get it * @page: the page to lock *
@@ -2540,6 +2553,9 @@ out:* (presumably at page->private). If the release was successful, return `1'. * Otherwise return zero. * +* This may also be called if PG_fscache is set on a page, indicating that the +* page is known to the local caching routines. +* * The @gfp_mask argument specifies whether I/O may be performed to release * this page (__GFP_IO), and whether the call may block (__GFP_WAIT). *
mm/migrate.c +1 -1
@@ -545,7 +545,7 @@ static int fallback_migrate_page(struct address_space *mapping,* Buffers may be managed in a filesystem specific way. * We must have no buffers or drop them. */ -if (PagePrivate (page) && +if (page_has_private (page) && !try_to_release_page (page,GFP_KERNEL ))return -EAGAIN ;
mm/page_alloc.c +3 -0
@@ -230,6 +230,7 @@ static void bad_page(struct page *page)dump_stack (); page->flags &= ~(1 << PG_lru | 1 << PG_private | + 1 << PG_fscache | 1 << PG_locked | 1 << PG_active | 1 << PG_dirty |
@@ -456,6 +457,7 @@ static inline int free_pages_check(struct page *page) (page->flags & ( 1 << PG_lru | 1 << PG_private | + 1 << PG_fscache | 1 << PG_locked | 1 << PG_active | 1 << PG_slab |
@@ -605,6 +607,7 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags) (page->flags & ( 1 << PG_lru | 1 << PG_private | + 1 << PG_fscache | 1 << PG_locked | 1 << PG_active | 1 << PG_dirty |
mm/readahead.c +5 -4
@@ -46,14 +46,15 @@ EXPORT_SYMBOL_GPL(file_ra_state_init);/* * see if a page needs releasing upon read_cache_pages() failure -* - the caller of read_cache_pages() may have set PG_private before calling, -* such as the NFS fs marking pages that are cached locally on disk, thus we -* need to give the fs a chance to clean up in the event of an error +* - the caller of read_cache_pages() may have set PG_private or PG_fscache +* before calling, such as the NFS fs marking pages that are cached locally +* on disk, thus we need to give the fs a chance to clean up in the event of +* an error */ static void read_cache_pages_invalidate_page (struct address_space *mapping,struct page *page) { -if (PagePrivate (page)) { +if (page_has_private (page)) {if (TestSetPageLocked (page))BUG (); page->mapping = mapping;
mm/swap.c +2 -2
@@ -455,8 +455,8 @@ void pagevec_strip(struct pagevec *pvec)for (i =0 ; i <pagevec_count (pvec); i++) {struct page *page = pvec->pages[i]; -if (PagePrivate (page) && !TestSetPageLocked (page)) { -if (PagePrivate (page)) +if (page_has_private (page) && !TestSetPageLocked (page)) { +if (page_has_private (page))try_to_release_page (page,0 );unlock_page (page); }
mm/swap_state.c +2 -2
@@ -76,7 +76,7 @@ static int __add_to_swap_cache(struct page *page, swp_entry_t entry,BUG_ON (!PageLocked (page));BUG_ON (PageSwapCache (page)); -BUG_ON (PagePrivate (page)); +BUG_ON (page_has_private (page)); error =radix_tree_preload (gfp_mask);if (!error) {write_lock_irq (&swapper_space.tree_lock);
@@ -129,7 +129,7 @@ void __delete_from_swap_cache(struct page *page)BUG_ON (!PageLocked (page));BUG_ON (!PageSwapCache (page));BUG_ON (PageWriteback (page)); -BUG_ON (PagePrivate (page)); +BUG_ON (page_has_private (page));radix_tree_delete (&swapper_space.page_tree,page_private (page));set_page_private (page,0 );
mm/truncate.c +5 -5
@@ -49,7 +49,7 @@ void do_invalidatepage(struct page *page, unsigned long offset)static inline void truncate_partial_page (struct page *page,unsigned partial) {zero_user_page (page, partial,PAGE_CACHE_SIZE - partial,KM_USER0 ); -if (PagePrivate (page)) +if (page_has_private (page))do_invalidatepage (page, partial); }
@@ -100,7 +100,7 @@ truncate_complete_page(struct address_space *mapping, struct page *page)cancel_dirty_page (page,PAGE_CACHE_SIZE ); -if (PagePrivate (page)) +if (page_has_private (page))do_invalidatepage (page,0 );remove_from_page_cache (page);
@@ -125,7 +125,7 @@ invalidate_complete_page(struct address_space *mapping, struct page *page)if (page->mapping != mapping)return 0 ; -if (PagePrivate (page) && !try_to_release_page (page,0 )) +if (page_has_private (page) && !try_to_release_page (page,0 ))return 0 ; ret =remove_mapping (mapping, page);
@@ -347,14 +347,14 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)if (page->mapping != mapping)return 0 ; -if (PagePrivate (page) && !try_to_release_page (page,GFP_KERNEL )) +if (page_has_private (page) && !try_to_release_page (page,GFP_KERNEL ))return 0 ;write_lock_irq (&mapping->tree_lock);if (PageDirty (page)) goto failed; -BUG_ON (PagePrivate (page)); +BUG_ON (page_has_private (page));__remove_from_page_cache (page);write_unlock_irq (&mapping->tree_lock);ClearPageUptodate (page);
mm/vmscan.c +1 -1
@@ -578,7 +578,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,* process address space (page_count == 1) it can be freed. * Otherwise, leave the page on the LRU so it is swappable. */ -if (PagePrivate (page)) { +if (page_has_private (page)) {if (!try_to_release_page (page, sc->gfp_mask)) goto activate_locked;if (!mapping &&page_count (page) ==1 )
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 14/26 FS-Cache: Provide an add_wait_queue_tail() function
In reply to David HowellsProvide an add_wait_queue_tail() function to add a waiter to the back of a wait queue instead of the front.
---
include/linux/wait.h | 2 ++ kernel/wait.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 0 deletions(-)
include/linux/wait.h +2 -0
@@ -118,6 +118,8 @@ static inline int waitqueue_active(wait_queue_head_t *q)#define is_sync_wait (wait) (!(wait) || ((wait)->private))extern void FASTCALL (add_wait_queue (wait_queue_head_t *q,wait_queue_t * wait)); +extern void FASTCALL (add_wait_queue_tail (wait_queue_head_t *q, +wait_queue_t *wait));extern void FASTCALL (add_wait_queue_exclusive (wait_queue_head_t *q,wait_queue_t * wait));extern void FASTCALL (remove_wait_queue (wait_queue_head_t *q,wait_queue_t * wait));
kernel/wait.c +18 -0
@@ -29,6 +29,24 @@ void fastcall add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) }EXPORT_SYMBOL (add_wait_queue); +/** +* add_wait_queue_tail - Add a waiter to the back of a waitqueue +* @q: the wait queue to append the waiter to +* @wait: the waiter to be queued +* +* Add a waiter to the back of a waitqueue so that it gets woken up last. +*/ +void fastcall add_wait_queue_tail(wait_queue_head_t *q, wait_queue_t *wait) +{ +unsigned long flags; + + wait->flags &= ~WQ_FLAG_EXCLUSIVE ; +spin_lock_irqsave (&q->lock, flags); +__add_wait_queue_tail (q, wait); +spin_unlock_irqrestore (&q->lock, flags); +} +EXPORT_SYMBOL (add_wait_queue_tail); + void fastcall add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait) {unsigned long flags;
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 15/26 FS-Cache: Generic filesystem caching facility
In reply to David HowellsThe attached patch adds a generic intermediary (FS-Cache) by which filesystems may call on local caching capabilities, and by which local caching backends may make caches available:
+---------+ | | +--------------+ | NFS |--+ | | | | | +-->| CacheFS | +---------+ | +----------+ | | /dev/hda5 | | | | | +--------------+ +---------+ +-->| | | | | | |--+ | AFS |----->| FS-Cache | | | | |--+ +---------+ +-->| | | | | | | +--------------+ +---------+ | +----------+ | | | | | | +-->| CacheFiles | | ISOFS |--+ | /var/cache | | | +--------------+ +---------+
The patch also documents the netfs interface and the cache backend interface provided by the facility.
There are a number of reasons why I'm not using i_mapping to do this. These have been discussed a lot on the LKML and CacheFS mailing lists, but to summarise the basics:
(1) Most filesystems don't do hole reportage. Holes in files are treated as blocks of zeros and can't be distinguished otherwise, making it difficult to distinguish blocks that have been read from the network and cached from those that haven't.
(2) The backing inode must be fully populated before being exposed to userspace through the main inode because the VM/VFS goes directly to the backing inode and does not interrogate the front inode on VM ops.
Therefore:
(a) The backing inode must fit entirely within the cache.
(b) All backed files currently open must fit entirely within the cache at the same time.
(c) A working set of files in total larger than the cache may not be cached.
(d) A file may not grow larger than the available space in the cache.
(e) A file that's open and cached, and remotely grows larger than the cache is potentially stuffed.
(3) Writes go to the backing filesystem, and can only be transferred to the network when the file is closed.
(4) There's no record of what changes have been made, so the whole file must be written back.
(5) The pages belong to the backing filesystem, and all metadata associated with that page are relevant only to the backing filesystem, and not anything stacked atop it.
The attached patch adds a generic core to which both networking filesystems and caches may bind. It transfers requests from networking filesystems to appropriate caches if possible, or else gracefully denies them.
If this facility is disabled in the kernel configuration, then all its operations will be trivially reducible to nothing by the compiler.
FS-Cache provides the following facilities:
(1) Caches can be added / removed at any time, even whilst in use.
(2) Adds a facility by which tags can be used to refer to caches, even if they're not mounted yet.
(3) More than one cache can be used at once. Caches can be selected explicitly by use of tags.
(4) The netfs is provided with an interface that allows either party to withdraw caching facilities from a file (required for (1)).
(5) A netfs may annotate cache objects that belongs to it.
(6) Cache objects can be pinned and reservations made.
(7) The interface to the netfs returns as few errors as possible, preferring rather to let the netfs remain oblivious.
(8) Cookies are used to represent indices, files and other objects to the netfs. The simplest cookie is just a NULL pointer - indicating nothing cached there.
(9) The netfs is allowed to propose - dynamically - any index hierarchy it desires, though it must be aware that the index search function is recursive, stack space is limited, and indices can only be children of indices.
(10) Indices can be used to group files together to reduce key size and to make group invalidation easier. The use of indices may make lookup quicker, but that's cache dependent.
(11) Data I/O is effectively done directly to and from the netfs's pages. The netfs indicates that page A is at index B of the data-file represented by cookie C, and that it should be read or written. The cache backend may or may not start I/O on that page, but if it does, a netfs callback will be invoked to indicate completion. The I/O may be either synchronous or asynchronous.
(12) Cookies can be "retired" upon release. At this point FS-Cache will mark them as obsolete and the index hierarchy rooted at that point will get recycled.
(13) The netfs provides a "match" function for index searches. In addition to saying whether a match was made or not, this can also specify that an entry should be updated or deleted.
FS-Cache maintains a virtual indexing tree in which all indices, files, objects and pages are kept. Bits of this tree may actually reside in one or more caches.
FSDEF
|
+------------------------------------+
| |
NFS AFS
| |
+--------------------------+ +-----------+
| | | |
homedir mirror afs.org redhat.com
| | |
+------------+ +---------------+ +----------+
| | | | | |
00001 00002 00007 00125 vol00001 vol00002
| | | | |
+---+---+ +-----+ +---+ +------+------+ +-----+----+
| | | | | | | | | | | | |
PG0 PG1 PG2 PG0 XATTR PG0 PG1 DIRENT DIRENT DIRENT R/W R/O Bak
| |
PG0 +-------+
| |
00001 00003
|
+---+---+
| | |
PG0 PG1 PG2In the example above, you can see two netfs's being backed: NFS and AFS. These have different index hierarchies:
(*) The NFS primary index will probably contain per-server indices. Each
server index is indexed by NFS file handles to get data file objects. Each data file objects can have an array of pages, but may also have further child objects, such as extended attributes and directory entries. Extended attribute objects themselves have page-array contents.
(*) The AFS primary index contains per-cell indices. Each cell index contains
per-logical-volume indices. Each of volume index contains up to three indices for the read-write, read-only and backup mirrors of those volumes. Each of these contains vnode data file objects, each of which contains an array of pages.
The very top index is the FS-Cache master index in which individual netfs's have entries.
Any index object may reside in more than one cache, provided it only has index children. Any index with non-index object children will be assumed to only reside in one cache.
The FS-Cache overview can be found in:
Documentation/filesystems/caching/fscache.txt
The netfs API to FS-Cache can be found in:
Documentation/filesystems/caching/netfs-api.txt
The cache backend API to FS-Cache can be found in:
Documentation/filesystems/caching/backend-api.txt
---
Documentation/filesystems/caching/backend-api.txt | 625 +++++++++++++++ Documentation/filesystems/caching/fscache.txt | 295 +++++++ Documentation/filesystems/caching/netfs-api.txt | 741 ++++++++++++++++++ fs/Kconfig | 6 fs/Makefile | 1 fs/fscache/Kconfig | 49 + fs/fscache/Makefile | 19 fs/fscache/fsc-cache.c | 506 ++++++++++++ fs/fscache/fsc-cookie.c | 490 ++++++++++++ fs/fscache/fsc-fsdef.c | 112 +++ fs/fscache/fsc-internal.h | 376 +++++++++ fs/fscache/fsc-main.c | 133 +++ fs/fscache/fsc-manage.c | 257 ++++++ fs/fscache/fsc-object.c | 583 ++++++++++++++ fs/fscache/fsc-page.c | 872 +++++++++++++++++++++ fs/fscache/fsc-proc.c | 398 ++++++++++ fs/fscache/fsc-stats.c | 103 ++ fs/fscache/fsc-threads.c | 676 ++++++++++++++++ include/linux/fscache-cache.h | 433 ++++++++++ include/linux/fscache.h | 593 ++++++++++++++ 20 files changed, 7268 insertions(+), 0 deletions(-) create mode 100644 Documentation/filesystems/caching/backend-api.txt create mode 100644 Documentation/filesystems/caching/fscache.txt create mode 100644 Documentation/filesystems/caching/netfs-api.txt create mode 100644 fs/fscache/Kconfig create mode 100644 fs/fscache/Makefile create mode 100644 fs/fscache/fsc-cache.c create mode 100644 fs/fscache/fsc-cookie.c create mode 100644 fs/fscache/fsc-fsdef.c create mode 100644 fs/fscache/fsc-internal.h create mode 100644 fs/fscache/fsc-main.c create mode 100644 fs/fscache/fsc-manage.c create mode 100644 fs/fscache/fsc-object.c create mode 100644 fs/fscache/fsc-page.c create mode 100644 fs/fscache/fsc-proc.c create mode 100644 fs/fscache/fsc-stats.c create mode 100644 fs/fscache/fsc-threads.c create mode 100644 include/linux/fscache-cache.h create mode 100644 include/linux/fscache.h
Documentation/filesystems/caching/backend-api.txt new file +625 -0
@@ -0,0 +1,625 @@ + ========================== + FS-CACHE CACHE BACKEND API + ========================== + +The FS-Cache system provides an API by which actual caches can be supplied to +FS-Cache for it to then serve out to network filesystems and other interested +parties. + +This API is declared in <linux/fscache-cache.h>. + + +==================================== +INITIALISING AND REGISTERING A CACHE +==================================== + +To start off, a cache definition must be initialised and registered for each +cache the backend wants to make available. For instance, CacheFS does this in +the fill_super() operation on mounting. + +The cache definition (struct fscache_cache) should be initialised by calling: + + void fscache_init_cache(struct fscache_cache *cache, + struct fscache_cache_ops *ops, + const char *idfmt, + ...); + +Where: + + (*) "cache" is a pointer to the cache definition; + + (*) "ops" is a pointer to the table of operations that the backend supports on + this cache; and + + (*) "idfmt" is a format and printf-style arguments for constructing a label + for the cache. + + +The cache should then be registered with FS-Cache by passing a pointer to the +previously initialised cache definition to: + + int fscache_add_cache(struct fscache_cache *cache, + struct fscache_object *fsdef, + const char *tagname); + +Two extra arguments should also be supplied: + + (*) "fsdef" which should point to the object representation for the FS-Cache + master index in this cache. Netfs primary index entries will be created + here. + + (*) "tagname" which, if given, should be a text string naming this cache. If + this is NULL, the identifier will be used instead. For CacheFS, the + identifier is set to name the underlying block device and the tag can be + supplied by mount. + +This function may return -ENOMEM if it ran out of memory or -EEXIST if the tag +is already in use. 0 will be returned on success. + + +===================== +UNREGISTERING A CACHE +===================== + +A cache can be withdrawn from the system by calling this function with a +pointer to the cache definition: + + void fscache_withdraw_cache(struct fscache_cache *cache); + +In CacheFS's case, this is called by put_super(). + + +======== +SECURITY +======== + +The cache methods are executed one of two contexts: + + (1) that of the userspace process that issued the netfs operation that caused + the cache method to be invoked, or + + (2) that of one of the processes in the FS-Cache thread pool. + +In either case, this may not be an appropriate context in which to access the +cache. + +The calling process's fsuid, fsgid and SELinux security identities may need to +be masqueraded for the duration of the cache driver's access to the cache. +This is left to the cache to handle; FS-Cache makes no effort in this regard. + + +=================================== +CONTROL AND STATISTICS PRESENTATION +=================================== + +The cache may present data to the outside world through FS-Cache's interfaces +in sysfs and procfs - the former for control and the latter for statistics. + +A sysfs directory called /sys/fs/fscache/<cachetag>/ is created if CONFIG_SYSFS +is enabled. This is accessible through the kobject struct fscache_cache::kobj +and is for use by the cache as it sees fit. + +The cache driver may create itself a directory named for the cache type in the +/proc/fs/fscache/ directory. This is available if CONFIG_FSCACHE_PROC is +enabled and is accessible through: + + struct proc_dir_entry *proc_fscache; + + +======================== +RELEVANT DATA STRUCTURES +======================== + + (*) Index/Data file FS-Cache representation cookie: + + struct fscache_cookie { + struct fscache_object_def *def; + struct fscache_netfs *netfs; + void *netfs_data; + ... + }; + + The fields that might be of use to the backend describe the object + definition, the netfs definition and the netfs's data for this cookie. + The object definition contain functions supplied by the netfs for loading + and matching index entries; these are required to provide some of the + cache operations. + + + (*) In-cache object representation: + + struct fscache_object { + int debug_id; + enum { + FSCACHE_OBJECT_RECYCLING, + ... + } state; + spinlock_t lock + struct fscache_cache *cache; + struct fscache_cookie *cookie; + ... + }; + + Structures of this type should be allocated by the cache backend and + passed to FS-Cache when requested by the appropriate cache operation. In + the case of CacheFS, they're embedded in CacheFS's internal object + structures. + + The debug_id is a simple integer that can be used in debugging messages + that refer to a particular object. In such a case it should be printed + using "OBJ%x" to be consistent with FS-Cache. + + Each object contains a pointer to the cookie that represents the object it + is backing. An object should retired when put_object() is called if it is + in state FSCACHE_OBJECT_RECYCLING. The fscache_object struct should be + initialised by calling fscache_object_init(object). + + + (*) FS-Cache operation record: + + struct fscache_operation { + atomic_t usage; + struct fscache_object *object; + unsigned long flags; + #define FSCACHE_OP_EXCLUSIVE + void (*processor)(struct fscache_operation *op); + void (*release)(struct fscache_operation *op); + ... + }; + + FS-Cache has a pool of threads that it uses to give CPU time to the + various asynchronous operations that need to be done as part of driving + the cache. These are represented by the above structure. The processor + method is called to give the op CPU time, and the release method to get + rid of it when its usage count reaches 0. + + An operation can be made exclusive upon an object by setting the + appropriate flag before enqueuing it with fscache_enqueue_operation(). If + an operation needs more processing time, it should be enqueued again. + + + (*) FS-Cache retrieval operation record: + + struct fscache_retrieval { + struct fscache_operation op; + struct address_space *mapping; + struct list_head *to_do; + ... + }; + + A structure of this type is allocated by FS-Cache to record retrieval and + allocation requests made by the netfs. This struct is then passed to the + backend to do the operation. The backend may get extra refs to it by + calling fscache_get_retrieval() and refs may be discarded by calling + fscache_put_retrieval(). + + A retrieval operation can be used by the backend to do retrieval work. To + do this, the retrieval->op.processor method pointer should be set + appropriately by the backend and fscache_enqueue_retrieval() called to + submit it to the thread pool. CacheFiles, for example, uses this to queue + page examination when it detects PG_lock being cleared. + + The to_do field is an empty list available for the cache backend to use as + it sees fit. + + + (*) FS-Cache storage operation record: + + struct fscache_storage { + struct fscache_operation op; + pgoff_t store_limit; + ... + }; + + A structure of this type is allocated by FS-Cache to record outstanding + writes to be made. FS-Cache itself enqueues this operation and invokes + the write_page() method on the object at appropriate times to effect + storage. + + +================ +CACHE OPERATIONS +================ + +The cache backend provides FS-Cache with a table of operations that can be +performed on the denizens of the cache. These are held in a structure of type: + + struct fscache_cache_ops + + (*) Name of cache provider [mandatory]: + + const char *name + + This isn't strictly an operation, but should be pointed at a string naming + the backend. + + + (*) Allocate a new object [mandatory]: + + struct fscache_object *(*alloc_object)(struct fscache_cache *cache, + struct fscache_cookie *cookie) + + This method is used to allocate a cache object representation to back a + cookie in a particular cache. fscache_object_init() should be called on + the object to initialise it prior to returning. + + This function may also be used to parse the index key to be used for + multiple lookup calls to turn it into a more convenient form. FS-Cache + will call the lookup_complete() method to allow the cache to release the + form once lookup is complete or aborted. + + + (*) Look up and create object [mandatory]: + + void (*lookup_object)(struct fscache_object *object) + + This method is used to look up an object, given that the object is already + allocated and attached to the cookie. This should instantiate that object + in the cache if it can. + + The method should call fscache_object_lookup_negative() as soon as + possible if it determines the object doesn't exist in the cache. If the + object is found to exist and the netfs indicates that it is valid then + fscache_obtained_object() should be called once the object is in a + position to have data stored in it. Similarly, fscache_obtained_object() + should also be called once a non-present object has been created. + + If a lookup error occurs, fscache_object_lookup_error() should be called + to abort the lookup of that object. + + + (*) Release lookup data [mandatory]: + + void (*lookup_complete)(struct fscache_object *object) + + This method is called to ask the cache to release any resources it was + using to perform a lookup. + + + (*) Increment object refcount [mandatory]: + + struct fscache_object *(*grab_object)(struct fscache_object *object) + + This method is called to increment the reference count on an object. It + may fail (for instance if the cache is being withdrawn) by returning NULL. + It should return the object pointer if successful. + + + (*) Lock/Unlock object [mandatory]: + + void (*lock_object)(struct fscache_object *object) + void (*unlock_object)(struct fscache_object *object) + + These methods are used to exclusively lock an object. It must be possible + to schedule with the lock held, so a spinlock isn't sufficient. + + + (*) Pin/Unpin object [optional]: + + int (*pin_object)(struct fscache_object *object) + void (*unpin_object)(struct fscache_object *object) + + These methods are used to pin an object into the cache. Once pinned an + object cannot be reclaimed to make space. Return -ENOSPC if there's not + enough space in the cache to permit this. + + + (*) Update object [mandatory]: + + int (*update_object)(struct fscache_object *object) + + This is called to update the index entry for the specified object. The + new information should be in object->cookie->netfs_data. This can be + obtained by calling object->cookie->def->get_aux()/get_attr(). + + + (*) Discard object [mandatory]: + + void (*drop_object)(struct fscache_object *object) + + This method is called to indicate that an object has been unbound from its + cookie, and that the cache should release the object's resources and + retire it if it's in state FSCACHE_OBJECT_RECYCLING. + + This method should not attempt to release any references held by the + caller. The caller will invoke the put_object() method as appropriate. + + + (*) Release object reference [mandatory]: + + void (*put_object)(struct fscache_object *object) + + This method is used to discard a reference to an object. The object may + be freed when all the references to it are released. + + + (*) Synchronise a cache [mandatory]: + + void (*sync)(struct fscache_cache *cache) + + This is called to ask the backend to synchronise a cache with its backing + device. + + + (*) Dissociate a cache [mandatory]: + + void (*dissociate_pages)(struct fscache_cache *cache) + + This is called to ask a cache to perform any page dissociations as part of + cache withdrawal. + + + (*) Notification that the attributes on a netfs file changed [mandatory]: + + int (*attr_changed)(struct fscache_object *object); + + This is called to indicate to the cache that certain attributes on a netfs + file have changed (for example the maximum size a file may reach). The + cache can read these from the netfs by calling the cookie's get_attr() + method. + + The cache may use the file size information to reserve space on the cache. + It should also call fscache_set_store_limit() to indicate to FS-Cache the + highest byte it's willing to store for an object. + + This method may return -ve if an error occurred or the cache object cannot + be expanded. In such a case, the object will be withdrawn from service. + + This operation is run asynchronously from FS-Cache's thread pool, and + storage and retrieval operations from the netfs are excluded during the + execution of this operation. + + + (*) Reserve cache space for an object's data [optional]: + + int (*reserve_space)(struct fscache_object *object, loff_t size); + + This is called to request that cache space be reserved to hold the data + for an object and the metadata used to track it. Zero size should be + taken as request to cancel a reservation. + + This should return 0 if successful, -ENOSPC if there isn't enough space + available, or -ENOMEM or -EIO on other errors. + + The reservation may exceed the current size of the object, thus permitting + future expansion. If the amount of space consumed by an object would + exceed the reservation, it's permitted to refuse requests to allocate + pages, but not required. An object may be pruned down to its reservation + size if larger than that already. + + + (*) Request page be read from cache [mandatory]: + + int (*read_or_alloc_page)(struct fscache_retrieval *op, + struct page *page, + gfp_t gfp) + + This is called to attempt to read a netfs page from the cache, or to + reserve a backing block if not. FS-Cache will have done as much checking + as it can before calling, but most of the work belongs to the backend. + + If there's no page in the cache, then -ENODATA should be returned if the + backend managed to reserve a backing block; -ENOBUFS or -ENOMEM if it + didn't. + + If there is suitable data in the cache, then a read operation should be + queued and 0 returned. When the read finishes, fscache_end_io() should be + called. + + The fscache_mark_pages_cached() should be called for the page if any cache + metadata is retained. This will indicate to the netfs that the page needs + explicit uncaching. This operation takes a pagevec, thus allowing several + pages to be marked at once. + + The retrieval record pointed to by op should be retained for each page + queued and released when I/O on the page has been formally ended. + fscache_get/put_retrieval() are available for this purpose. + + The retrieval record may be used to get CPU time via the FS-Cache thread + pool. If this is desired, the op->op.processor should be set to point to + the appropriate processing routine, and fscache_enqueue_retrieval() should + be called at an appropriate point to request CPU time. For instance, the + retrieval routine could be enqueued upon the completion of a disk read. + The to_do field in the retrieval record is provided to aid in this. + + If an I/O error occurs, fscache_io_error() should be called and -ENOBUFS + returned if possible or fscache_end_io() called with a suitable error + code.. + + + (*) Request pages be read from cache [mandatory]: + + int (*read_or_alloc_pages)(struct fscache_retrieval *op, + struct list_head *pages, + unsigned *nr_pages, + gfp_t gfp) + + This is like the read_or_alloc_page() method, except it is handed a list + of pages instead of one page. Any pages on which a read operation is + started must be added to the page cache for the specified mapping and also + to the LRU. Such pages must also be removed from the pages list and + *nr_pages decremented per page. + + If there was an error such as -ENOMEM, then that should be returned; else + if one or more pages couldn't be read or allocated, then -ENOBUFS should + be returned; else if one or more pages couldn't be read, then -ENODATA + should be returned. If all the pages are dispatched then 0 should be + returned. + + + (*) Request page be allocated in the cache [mandatory]: + + int (*allocate_page)(struct fscache_retrieval *op, + struct page *page, + gfp_t gfp) + + This is like the read_or_alloc_page() method, except that it shouldn't + read from the cache, even if there's data there that could be retrieved. + It should, however, set up any internal metadata required such that + the write_page() method can write to the cache. + + If there's no backing block available, then -ENOBUFS should be returned + (or -ENOMEM if there were other problems). If a block is successfully + allocated, then the netfs page should be marked and 0 returned. + + + (*) Request pages be allocated in the cache [mandatory]: + + int (*allocate_pages)(struct fscache_retrieval *op, + struct list_head *pages, + unsigned *nr_pages, + gfp_t gfp) + + This is an multiple page version of the allocate_page() method. pages and + nr_pages should be treated as for the read_or_alloc_pages() method. + + + (*) Request page be written to cache [mandatory]: + + int (*write_page)(struct fscache_storage *op, + struct page *page); + + This is called to write from a page on which there was a previously + successful read_or_alloc_page() call or similar. FS-Cache filters out + pages that don't have mappings. + + This method is called asynchronously from the FS-Cache thread pool. It is + not required to actually store anything, provided -ENODATA is then + returned to the next read of this page. + + If an error occurred, then a negative error code should be returned, + otherwise zero should be returned. FS-Cache will take appropriate action + in response to an error, such as withdrawing this object. + + If this method returns success then FS-Cache will inform the netfs + appropriately. + + + (*) Discard retained per-page metadata [mandatory]: + + void (*uncache_page)(struct fscache_object *object, struct page *page) + + This is called when a netfs page is being evicted from the pagecache. The + cache backend should tear down any internal representation or tracking it + maintains for this page. + + +================== +FS-CACHE UTILITIES +================== + +FS-Cache provides some utilities that a cache backend may make use of: + + (*) Note occurrence of an I/O error in a cache: + + void fscache_io_error(struct fscache_cache *cache) + + This tells FS-Cache that an I/O error occurred in the cache. After this + has been called, only resource dissociation operations (object and page + release) will be passed from the netfs to the cache backend for the + specified cache. + + This does not actually withdraw the cache. That must be done separately. + + + (*) Invoke the retrieval I/O completion function: + + void fscache_end_io(struct fscache_retrieval *op, struct page *page, + int error); + + This is called to note the end of an attempt to retrieve a page. The + error value should be 0 if successful and an error otherwise. + + + (*) Set highest store limit: + + void fscache_set_store_limit(struct fscache_object *object, + loff_t i_size); + + This sets the limit FS-Cache imposes on the highest byte it's willing to + try and store for a netfs. Any page over this limit is automatically + rejected by fscache_read_alloc_page() and co with -ENOBUFS. + + + (*) Mark pages as being cached: + + void fscache_mark_pages_cached(struct fscache_retrieval *op, + struct pagevec *pagevec); + + This marks a set of pages as being cached. After this has been called, + the netfs must call fscache_uncache_page() to unmark the pages. + + + (*) Initialise a freshly allocated object: + + void fscache_object_init(struct fscache_object *object); + + This initialises all the fields in an object representation. + + + (*) Indicate negative lookup on an object: + + void fscache_object_lookup_negative(struct fscache_object *object); + + This is called to indicate to FS-Cache that a lookup process for an object + found a negative result. + + This changes the state of an object to permit reads pending on lookup + completion to go off and start fetching data from the netfs server as it's + known at this point that there can't be any data in the cache. + + This may be called multiple times on an object. Only the first call is + significant - all subsequent calls are ignored. + + + (*) Indicate an object has been obtained: + + void fscache_obtained_object(struct fscache_object *object); + + This is called to indicate to FS-Cache that a lookup process for an object + produced a positive result, or that an object was created. This should + only be called once for any particular object. + + This changes the state of an object to indicate: + + (1) if no call to fscache_object_lookup_negative() has been made on + this object, that there may be data available, and that reads can + now go and look for it; and + + (2) that writes may now proceed against this object. + + + (*) Indicate that object lookup failed: + + void fscache_object_lookup_error(struct fscache_object *object); + + This marks an object as having encountered a fatal error (usually EIO) + and causes it to move into a state whereby it will be withdrawn as soon + as possible. + + + (*) Get and release references on a retrieval record: + + void fscache_get_retrieval(struct fscache_retrieval *op); + void fscache_put_retrieval(struct fscache_retrieval *op); + + These two functions are used to retain a retrieval record whilst doing + asynchronous data retrieval and block allocation. + + + (*) Enqueue a retrieval record for processing. + + void fscache_enqueue_retrieval(struct fscache_retrieval *op); + + This enqueues a retrieval record for processing by the FS-Cache thread + pool. One of the threads in the pool will invoke the retrieval record's + op->op.processor callback function. This function may be called from + within the callback function. + + + (*) List of object state names: + + const char *fscache_object_states[]; + + For debugging purposes, this may be used to turn the state that an object + is in into a text string for display purposes.
Documentation/filesystems/caching/fscache.txt new file +295 -0
295 lines not on this page · raw message
Documentation/filesystems/caching/netfs-api.txt new file +741 -0
741 lines not on this page · raw message
fs/Kconfig +6 -0
@@ -656,6 +656,12 @@ config GENERIC_ACL bool select FS_POSIX_ACL +menu "Caches" + +source "fs/fscache/Kconfig" + +endmenu + if BLOCK menu "CD-ROM/DVD Filesystems"
fs/Makefile +1 -0
@@ -65,6 +65,7 @@ obj-$(CONFIG_PROFILING) += dcookies.o obj-$(CONFIG_DLM) += dlm/ # Do not add any filesystems before this line +obj-$(CONFIG_FSCACHE) += fscache/ obj-$(CONFIG_REISERFS_FS) += reiserfs/ obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3 obj-$(CONFIG_EXT4DEV_FS) += ext4/ # Before ext2 so root fs can be ext4dev
fs/fscache/Kconfig new file +49 -0
49 lines not on this page · raw message
fs/fscache/Makefile new file +19 -0
@@ -0,0 +1,19 @@ +# +# Makefile for general filesystem caching code +# + +fscache-y := \ + fsc-cache.o \ + fsc-cookie.o \ + fsc-fsdef.o \ + fsc-main.o \ + fsc-manage.o \ + fsc-object.o \ + fsc-page.o \ + fsc-threads.o + +fscache-$(CONFIG_FSCACHE_PROC) += \ + fsc-proc.o \ + fsc-stats.o + +obj-$(CONFIG_FSCACHE) := fscache.o
fs/fscache/fsc-cache.c new file +506 -0
506 lines not on this page · raw message
fs/fscache/fsc-cookie.c new file +490 -0
490 lines not on this page · raw message
fs/fscache/fsc-fsdef.c new file +112 -0
112 lines not on this page · raw message
fs/fscache/fsc-internal.h new file +376 -0
144 lines not on this page · raw message
fs/fscache/fsc-main.c new file +133 -0
133 lines not on this page · raw message
fs/fscache/fsc-manage.c new file +257 -0
257 lines not on this page · raw message
fs/fscache/fsc-object.c new file +583 -0
583 lines not on this page · raw message
fs/fscache/fsc-page.c new file +872 -0
872 lines not on this page · raw message
fs/fscache/fsc-proc.c new file +398 -0
398 lines not on this page · raw message
fs/fscache/fsc-stats.c new file +103 -0
103 lines not on this page · raw message
fs/fscache/fsc-threads.c new file +676 -0
676 lines not on this page · raw message
include/linux/fscache-cache.h new file +433 -0
433 lines not on this page · raw message
include/linux/fscache.h new file +593 -0
593 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
David Howells
maintainerPATCH 16/26 CacheFiles: Add missing copy_page export for ia64
In reply to David HowellsThis one-line patch fixes the missing export of copy_page introduced by the cachefile patches. This patch is not yet upstream, but is required for cachefile on ia64. It will be pushed upstream when cachefile goes upstream.
---
arch/ia64/kernel/ia64_ksyms.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/ia64/kernel/ia64_ksyms.c +1 -0
@@ -43,6 +43,7 @@ EXPORT_SYMBOL(__do_clear_user);EXPORT_SYMBOL (__strlen_user);EXPORT_SYMBOL (__strncpy_from_user);EXPORT_SYMBOL (__strnlen_user); +EXPORT_SYMBOL (copy_page);/* from arch/ia64/lib */ extern void __divsi3 (void );
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 17/26 CacheFiles: Be consistent about the use of mapping vs file->f_mapping in Ext3
In reply to David HowellsChange all the usages of file->f_mapping in ext3_*write_end() functions to use the mapping argument directly. This has two consequences:
(*) Consistency. Without this patch sometimes one is used and sometimes the
other is.
(*) A NULL file pointer can be passed. This feature is then made use of by
the generic hook in the next patch, which is used by CacheFiles to write pages to a file without setting up a file struct.
---
fs/ext3/inode.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
fs/ext3/inode.c +3 -3
@@ -1227,7 +1227,7 @@ static int ext3_generic_write_end(struct file *file, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { - struct inode *inode = file->f_mapping->host; + struct inode *inode = mapping->host; copied =block_write_end (file, mapping, pos, len, copied, page, fsdata);
@@ -1252,7 +1252,7 @@ static int ext3_ordered_write_end(struct file *file, struct page *page, void *fsdata) { handle_t *handle = ext3_journal_current_handle(); -struct inode *inode = file->f_mapping->host; +struct inode *inode = mapping->host;unsigned from, to;int ret =0 , ret2;
@@ -1293,7 +1293,7 @@ static int ext3_writeback_write_end(struct file *file, struct page *page, void *fsdata) { handle_t *handle = ext3_journal_current_handle(); -struct inode *inode = file->f_mapping->host; +struct inode *inode = mapping->host;int ret =0 , ret2;loff_t new_i_size;
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 18/26 CacheFiles: Add a hook to write a single page of data to an inode
In reply to David HowellsAdd an address space operation to write one single page of data to an inode at a page-aligned location (thus permitting the implementation to be highly optimised). The data source is a single page.
This is used by CacheFiles to store the contents of netfs pages into their backing file pages.
Supply a generic implementation for this that uses the write_begin() and write_end() address_space operations to bind a copy directly into the page cache.
Hook the Ext2 and Ext3 operations to the generic implementation.
---
fs/ext2/inode.c | 2 ++ fs/ext3/inode.c | 3 +++ include/linux/fs.h | 7 ++++++ mm/filemap.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 0 deletions(-)
fs/ext2/inode.c +2 -0
@@ -796,6 +796,7 @@ const struct address_space_operations ext2_aops = { .direct_IO = ext2_direct_IO, .writepages = ext2_writepages, .migratepage = buffer_migrate_page, + .write_one_page = generic_file_buffered_write_one_page, };const struct address_space_operations ext2_aops_xip = {
@@ -814,6 +815,7 @@ const struct address_space_operations ext2_nobh_aops = { .direct_IO = ext2_direct_IO, .writepages = ext2_writepages, .migratepage = buffer_migrate_page, + .write_one_page = generic_file_buffered_write_one_page, };/*
fs/ext3/inode.c +3 -0
@@ -1780,6 +1780,7 @@ static const struct address_space_operations ext3_ordered_aops = { .releasepage = ext3_releasepage, .direct_IO = ext3_direct_IO, .migratepage = buffer_migrate_page, + .write_one_page = generic_file_buffered_write_one_page, };static const struct address_space_operations ext3_writeback_aops = {
@@ -1794,6 +1795,7 @@ static const struct address_space_operations ext3_writeback_aops = { .releasepage = ext3_releasepage, .direct_IO = ext3_direct_IO, .migratepage = buffer_migrate_page, + .write_one_page = generic_file_buffered_write_one_page, };static const struct address_space_operations ext3_journalled_aops = {
@@ -1807,6 +1809,7 @@ static const struct address_space_operations ext3_journalled_aops = { .bmap = ext3_bmap, .invalidatepage = ext3_invalidatepage, .releasepage = ext3_releasepage, + .write_one_page = generic_file_buffered_write_one_page, };void ext3_set_aops (struct inode *inode)
include/linux/fs.h +7 -0
@@ -479,6 +479,11 @@ struct address_space_operations {int (*migratepage) (struct address_space *,struct page *,struct page *);int (*launder_page) (struct page *); +/* write the contents of the source page over the page at the specified +* index in the target address space (the source page does not need to +* be related to the target address space) */ +int (*write_one_page)(struct address_space *,pgoff_t ,struct page *); + };/*
@@ -1801,6 +1806,8 @@ extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *, unsigned long *, loff_t, loff_t *, size_t, size_t);extern ssize_t generic_file_buffered_write (struct kiocb *,const struct iovec *,unsigned long ,loff_t ,loff_t *,size_t ,ssize_t ); +extern int generic_file_buffered_write_one_page (struct address_space *, +pgoff_t ,struct page *);extern ssize_t do_sync_read (struct file *filp,char __user *buf,size_t len,loff_t *ppos);extern ssize_t do_sync_write (struct file *filp,const char __user *buf,size_t len,loff_t *ppos); extern void do_generic_mapping_read(struct address_space *mapping,
mm/filemap.c +61 -0
67 lines not on this page · raw message
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 19/26 CacheFiles: Permit the page lock state to be monitored
In reply to David HowellsAdd a function to install a monitor on the page lock waitqueue for a particular page, thus allowing the page being unlocked to be detected.
This is used by CacheFiles to detect read completion on a page in the backing filesystem so that it can then copy the data to the waiting netfs page.
---
include/linux/pagemap.h | 5 +++++ mm/filemap.c | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 0 deletions(-)
include/linux/pagemap.h +5 -0
@@ -223,6 +223,11 @@ static inline void wait_on_page_fscache_write(struct page *page)extern void end_page_fscache_write (struct page *page);/* +* Add an arbitrary waiter to a page's wait queue +*/ +extern void add_page_wait_queue (struct page *page,wait_queue_t *waiter); + +/* * Fault a userspace page into pagetables. Return non-zero on a fault. * * This assumes that two userspace pages are always sufficient. That's
mm/filemap.c +18 -0
@@ -533,6 +533,24 @@ void fastcall wait_on_page_bit(struct page *page, int bit_nr)EXPORT_SYMBOL (wait_on_page_bit);/** +* add_page_wait_queue - Add an arbitrary waiter to a page's wait queue +* @page - Page defining the wait queue of interest +* @waiter - Waiter to add to the queue +* +* Add an arbitrary @waiter to the wait queue for the nominated @page. +*/ +void add_page_wait_queue (struct page *page,wait_queue_t *waiter) +{ +wait_queue_head_t *q =page_waitqueue (page); +unsigned long flags; + +spin_lock_irqsave (&q->lock, flags); +__add_wait_queue (q, waiter); +spin_unlock_irqrestore (&q->lock, flags); +} +EXPORT_SYMBOL_GPL (add_page_wait_queue); + +/** * unlock_page - unlock a locked page * @page: the page *
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 20/26 CacheFiles: Export things for CacheFiles
In reply to David HowellsExport a number of functions for CacheFiles's use.
---
fs/super.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
fs/super.c +1 -0
@@ -266,6 +266,7 @@ int fsync_super(struct super_block *sb)__fsync_super (sb);return sync_blockdev (sb->s_bdev); } +EXPORT_SYMBOL_GPL (fsync_super);/** * generic_shutdown_super - common helper for ->kill_sb()
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 21/26 CacheFiles: A cache that backs onto a mounted filesystem
In reply to David HowellsAdd an FS-Cache cache-backend that permits a mounted filesystem to be used as a backing store for the cache.
CacheFiles uses a userspace daemon to do some of the cache management - such as reaping stale nodes and culling. This is called cachefilesd and lives in /sbin. The source for the daemon can be downloaded from:
http://people.redhat.com/~dhowells/cachefs/cachefilesd.c
And an example configuration from:
http://people.redhat.com/~dhowells/cachefs/cachefilesd.conf
The filesystem and data integrity of the cache are only as good as those of the filesystem providing the backing services. Note that CacheFiles does not attempt to journal anything since the journalling interfaces of the various filesystems are very specific in nature.
CacheFiles creates a proc-file - "/proc/fs/cachefiles" - that is used for communication with the daemon. Only one thing may have this open at once, and whilst it is open, a cache is at least partially in existence. The daemon opens this and sends commands down it to control the cache.
CacheFiles is currently limited to a single cache.
CacheFiles attempts to maintain at least a certain percentage of free space on the filesystem, shrinking the cache by culling the objects it contains to make space if necessary - see the "Cache Culling" section. This means it can be placed on the same medium as a live set of data, and will expand to make use of spare space and automatically contract when the set of data requires more space.
============
REQUIREMENTS
============
The use of CacheFiles and its daemon requires the following features to be available in the system and in the cache filesystem:
- dnotify.
- extended attributes (xattrs).
- openat() and friends.
- bmap() support on files in the filesystem (FIBMAP ioctl).
- The use of bmap() to detect a partial page at the end of the file.
It is strongly recommended that the "dir_index" option is enabled on Ext3 filesystems being used as a cache.
=============
CONFIGURATION
=============
The cache is configured by a script in /etc/cachefilesd.conf. These commands set up cache ready for use. The following script commands are available:
(*) brun <N>%
(*) bcull <N>%
(*) bstop <N>%
Configure the culling limits. Optional. See the section on culling The defaults are 7%, 5% and 1% respectively.
(*) dir <path>
Specify the directory containing the root of the cache. Mandatory.
(*) tag <name>
Specify a tag to FS-Cache to use in distinguishing multiple caches. Optional. The default is "CacheFiles".
(*) debug <mask>
Specify a numeric bitmask to control debugging in the kernel module. Optional. The default is zero (all off).
==================
STARTING THE CACHE
==================
The cache is started by running the daemon. The daemon opens the cache proc file, configures the cache and tells it to begin caching. At that point the cache binds to fscache and the cache becomes live.
The daemon is run as follows:
/sbin/cachefilesd [-d]* [-s] [-n] [-f <configfile>]
The flags are:
(*) -d
Increase the debugging level. This can be specified multiple times and is cumulative with itself.
(*) -s
Send messages to stderr instead of syslog.
(*) -n
Don't daemonise and go into background.
(*) -f <configfile>
Use an alternative configuration file rather than the default one.
===============
THINGS TO AVOID
===============
Do not mount other things within the cache as this will cause problems. The kernel module contains its own very cut-down path walking facility that ignores mountpoints, but the daemon can't avoid them.
Do not create, rename or unlink files and directories in the cache whilst the cache is active, as this may cause the state to become uncertain.
Renaming files in the cache might make objects appear to be other objects (the filename is part of the lookup key).
Do not change or remove the extended attributes attached to cache files by the cache as this will cause the cache state management to get confused.
Do not create files or directories in the cache, lest the cache get confused or serve incorrect data.
Do not chmod files in the cache. The module creates things with minimal permissions to prevent random users being able to access them directly.
=============
CACHE CULLING
=============
The cache may need culling occasionally to make space. This involves discarding objects from the cache that have been used less recently than anything else. Culling is based on the access time of data objects. Empty directories are culled if not in use.
Cache culling is done on the basis of the percentage of blocks available in the underlying filesystem. There are three "limits":
(*) brun
If the amount of available space in the cache rises above this limit, then culling is turned off.
(*) bcull
If the amount of available space in the cache falls below this limit, then culling is started.
(*) bstop
If the amount of available space in the cache falls below this limit, then no further allocation of disk space is permitted until culling has raised the amount above this limit again.
These must be configured thusly:
0 <= bstop < bcull < brun < 100
Note that these are percentages of available space, and do _not_ appear as 100 minus the percentage displayed by the "df" program.
The userspace daemon scans the cache to build up a table of cullable objects. These are then culled in least recently used order. A new scan of the cache is started as soon as space is made in the table. Objects will be skipped if their atimes have changed or if the kernel module says it is still using them.
===============
CACHE STRUCTURE
===============
The CacheFiles module will create two directories in the directory it was given:
(*) cache/
(*) graveyard/
The active cache objects all reside in the first directory. The CacheFiles kernel module moves any retired or culled objects that it can't simply unlink to the graveyard from which the daemon will actually delete them.
The daemon uses dnotify to monitor the graveyard directory, and will delete anything that appears therein.
The module represents index objects as directories with the filename "I..." or "J...". Note that the "cache/" directory is itself a special index.
Data objects are represented as files if they have no children, or directories if they do. Their filenames all begin "D..." or "E...". If represented as a directory, data objects will have a file in the directory called "data" that actually holds the data.
Special objects are similar to data objects, except their filenames begin "S..." or "T...".
If an object has children, then it will be represented as a directory. Immediately in the representative directory are a collection of directories named for hash values of the child object keys with an '@' prepended. Into this directory, if possible, will be placed the representations of the child objects:
INDEX INDEX INDEX DATA FILES ========= ========== ================================= ================ cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400 cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...DB1ry cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...N22ry cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...FP1ry
If the key is so long that it exceeds NAME_MAX with the decorations added on to it, then it will be cut into pieces, the first few of which will be used to make a nest of directories, and the last one of which will be the objects inside the last directory. The names of the intermediate directories will have '+' prepended:
J1223/@23/+xy...z/+kl...m/Epqr
Note that keys are raw data, and not only may they exceed NAME_MAX in size, they may also contain things like '/' and NUL characters, and so they may not be suitable for turning directly into a filename.
To handle this, CacheFiles will use a suitably printable filename directly and "base-64" encode ones that aren't directly suitable. The two versions of object filenames indicate the encoding:
OBJECT TYPE PRINTABLE ENCODED =============== =============== =============== Index "I..." "J..." Data "D..." "E..." Special "S..." "T..."
Intermediate directories are always "@" or "+" as appropriate.
Each object in the cache has an extended attribute label that holds the object type ID (required to distinguish special objects) and the auxiliary data from the netfs. The latter is used to detect stale objects in the cache and update or retire them.
Note that CacheFiles will erase from the cache any file it doesn't recognise or any file of an incorrect type (such as a FIFO file or a device file).
This documentation is added by the patch to:
Documentation/filesystems/caching/cachefiles.txt
---
Documentation/filesystems/caching/cachefiles.txt | 395 ++++++++++ fs/Kconfig | 1 fs/Makefile | 1 fs/cachefiles/Kconfig | 33 + fs/cachefiles/Makefile | 18 fs/cachefiles/cf-bind.c | 289 +++++++ fs/cachefiles/cf-daemon.c | 754 +++++++++++++++++++ fs/cachefiles/cf-interface.c | 445 ++++++++++++ fs/cachefiles/cf-internal.h | 373 ++++++++++ fs/cachefiles/cf-key.c | 159 ++++ fs/cachefiles/cf-main.c | 108 +++ fs/cachefiles/cf-namei.c | 739 +++++++++++++++++++ fs/cachefiles/cf-proc.c | 166 ++++ fs/cachefiles/cf-rdwr.c | 851 ++++++++++++++++++++++ fs/cachefiles/cf-security.c | 105 +++ fs/cachefiles/cf-xattr.c | 292 ++++++++ security/security.c | 2 17 files changed, 4731 insertions(+), 0 deletions(-) create mode 100644 Documentation/filesystems/caching/cachefiles.txt create mode 100644 fs/cachefiles/Kconfig create mode 100644 fs/cachefiles/Makefile create mode 100644 fs/cachefiles/cf-bind.c create mode 100644 fs/cachefiles/cf-daemon.c create mode 100644 fs/cachefiles/cf-interface.c create mode 100644 fs/cachefiles/cf-internal.h create mode 100644 fs/cachefiles/cf-key.c create mode 100644 fs/cachefiles/cf-main.c create mode 100644 fs/cachefiles/cf-namei.c create mode 100644 fs/cachefiles/cf-proc.c create mode 100644 fs/cachefiles/cf-rdwr.c create mode 100644 fs/cachefiles/cf-security.c create mode 100644 fs/cachefiles/cf-xattr.c
Documentation/filesystems/caching/cachefiles.txt new file +395 -0
@@ -0,0 +1,395 @@ + =============================================== + CacheFiles: CACHE ON ALREADY MOUNTED FILESYSTEM + =============================================== + +Contents: + + (*) Overview. + + (*) Requirements. + + (*) Configuration. + + (*) Starting the cache. + + (*) Things to avoid. + + (*) Cache culling. + + (*) Cache structure. + + (*) Security model and SELinux. + +======== +OVERVIEW +======== + +CacheFiles is a caching backend that's meant to use as a cache a directory on +an already mounted filesystem of a local type (such as Ext3). + +CacheFiles uses a userspace daemon to do some of the cache management - such as +reaping stale nodes and culling. This is called cachefilesd and lives in +/sbin. + +The filesystem and data integrity of the cache are only as good as those of the +filesystem providing the backing services. Note that CacheFiles does not +attempt to journal anything since the journalling interfaces of the various +filesystems are very specific in nature. + +CacheFiles creates a misc character device - "/dev/cachefiles" - that is used +to communication with the daemon. Only one thing may have this open at once, +and whilst it is open, a cache is at least partially in existence. The daemon +opens this and sends commands down it to control the cache. + +CacheFiles is currently limited to a single cache. + +CacheFiles attempts to maintain at least a certain percentage of free space on +the filesystem, shrinking the cache by culling the objects it contains to make +space if necessary - see the "Cache Culling" section. This means it can be +placed on the same medium as a live set of data, and will expand to make use of +spare space and automatically contract when the set of data requires more +space. + + +============ +REQUIREMENTS +============ + +The use of CacheFiles and its daemon requires the following features to be +available in the system and in the cache filesystem: + + - dnotify. + + - extended attributes (xattrs). + + - openat() and friends. + + - bmap() support on files in the filesystem (FIBMAP ioctl). + + - The use of bmap() to detect a partial page at the end of the file. + +It is strongly recommended that the "dir_index" option is enabled on Ext3 +filesystems being used as a cache. + + +============= +CONFIGURATION +============= + +The cache is configured by a script in /etc/cachefilesd.conf. These commands +set up cache ready for use. The following script commands are available: + + (*) brun <N>% + (*) bcull <N>% + (*) bstop <N>% + (*) frun <N>% + (*) fcull <N>% + (*) fstop <N>% + + Configure the culling limits. Optional. See the section on culling + The defaults are 7% (run), 5% (cull) and 1% (stop) respectively. + + The commands beginning with a 'b' are file space (block) limits, those + beginning with an 'f' are file count limits. + + (*) dir <path> + + Specify the directory containing the root of the cache. Mandatory. + + (*) tag <name> + + Specify a tag to FS-Cache to use in distinguishing multiple caches. + Optional. The default is "CacheFiles". + + (*) debug <mask> + + Specify a numeric bitmask to control debugging in the kernel module. + Optional. The default is zero (all off). The following values can be + OR'd into the mask to collect various information: + + 1 Turn on trace of function entry (_enter() macros) + 2 Turn on trace of function exit (_leave() macros) + 4 Turn on trace of internal debug points (_debug()) + + This mask can also be set through sysfs, eg: + + echo 5 >/sys/modules/cachefiles/parameters/debug + + +================== +STARTING THE CACHE +================== + +The cache is started by running the daemon. The daemon opens the cache device, +configures the cache and tells it to begin caching. At that point the cache +binds to fscache and the cache becomes live. + +The daemon is run as follows: + + /sbin/cachefilesd [-d]* [-s] [-n] [-f <configfile>] + +The flags are: + + (*) -d + + Increase the debugging level. This can be specified multiple times and + is cumulative with itself. + + (*) -s + + Send messages to stderr instead of syslog. + + (*) -n + + Don't daemonise and go into background. + + (*) -f <configfile> + + Use an alternative configuration file rather than the default one. + + +=============== +THINGS TO AVOID +=============== + +Do not mount other things within the cache as this will cause problems. The +kernel module contains its own very cut-down path walking facility that ignores +mountpoints, but the daemon can't avoid them. + +Do not create, rename or unlink files and directories in the cache whilst the +cache is active, as this may cause the state to become uncertain. + +Renaming files in the cache might make objects appear to be other objects (the +filename is part of the lookup key). + +Do not change or remove the extended attributes attached to cache files by the +cache as this will cause the cache state management to get confused. + +Do not create files or directories in the cache, lest the cache get confused or +serve incorrect data. + +Do not chmod files in the cache. The module creates things with minimal +permissions to prevent random users being able to access them directly. + + +============= +CACHE CULLING +============= + +The cache may need culling occasionally to make space. This involves +discarding objects from the cache that have been used less recently than +anything else. Culling is based on the access time of data objects. Empty +directories are culled if not in use. + +Cache culling is done on the basis of the percentage of blocks and the +percentage of files available in the underlying filesystem. There are six +"limits": + + (*) brun + (*) frun + + If the amount of free space and the number of available files in the cache + rises above both these limits, then culling is turned off. + + (*) bcull + (*) fcull + + If the amount of available space or the number of available files in the + cache falls below either of these limits, then culling is started. + + (*) bstop + (*) fstop + + If the amount of available space or the number of available files in the + cache falls below either of these limits, then no further allocation of + disk space or files is permitted until culling has raised things above + these limits again. + +These must be configured thusly: + + 0 <= bstop < bcull < brun < 100 + 0 <= fstop < fcull < frun < 100 + +Note that these are percentages of available space and available files, and do +_not_ appear as 100 minus the percentage displayed by the "df" program. + +The userspace daemon scans the cache to build up a table of cullable objects. +These are then culled in least recently used order. A new scan of the cache is +started as soon as space is made in the table. Objects will be skipped if +their atimes have changed or if the kernel module says it is still using them. + + +=============== +CACHE STRUCTURE +=============== + +The CacheFiles module will create two directories in the directory it was +given: + + (*) cache/ + + (*) graveyard/ + +The active cache objects all reside in the first directory. The CacheFiles +kernel module moves any retired or culled objects that it can't simply unlink +to the graveyard from which the daemon will actually delete them. + +The daemon uses dnotify to monitor the graveyard directory, and will delete +anything that appears therein. + + +The module represents index objects as directories with the filename "I..." or +"J...". Note that the "cache/" directory is itself a special index. + +Data objects are represented as files if they have no children, or directories +if they do. Their filenames all begin "D..." or "E...". If represented as a +directory, data objects will have a file in the directory called "data" that +actually holds the data. + +Special objects are similar to data objects, except their filenames begin +"S..." or "T...". + + +If an object has children, then it will be represented as a directory. +Immediately in the representative directory are a collection of directories +named for hash values of the child object keys with an '@' prepended. Into +this directory, if possible, will be placed the representations of the child +objects: + + INDEX INDEX INDEX DATA FILES + ========= ========== ================================= ================ + cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400 + cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...DB1ry + cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...N22ry + cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...FP1ry + + +If the key is so long that it exceeds NAME_MAX with the decorations added on to +it, then it will be cut into pieces, the first few of which will be used to +make a nest of directories, and the last one of which will be the objects +inside the last directory. The names of the intermediate directories will have +'+' prepended: + + J1223/@23/+xy...z/+kl...m/Epqr + + +Note that keys are raw data, and not only may they exceed NAME_MAX in size, +they may also contain things like '/' and NUL characters, and so they may not +be suitable for turning directly into a filename. + +To handle this, CacheFiles will use a suitably printable filename directly and +"base-64" encode ones that aren't directly suitable. The two versions of +object filenames indicate the encoding: + + OBJECT TYPE PRINTABLE ENCODED + =============== =============== =============== + Index "I..." "J..." + Data "D..." "E..." + Special "S..." "T..." + +Intermediate directories are always "@" or "+" as appropriate. + + +Each object in the cache has an extended attribute label that holds the object +type ID (required to distinguish special objects) and the auxiliary data from +the netfs. The latter is used to detect stale objects in the cache and update +or retire them. + + +Note that CacheFiles will erase from the cache any file it doesn't recognise or +any file of an incorrect type (such as a FIFO file or a device file). + + +========================== +SECURITY MODEL AND SELINUX +========================== + +CacheFiles is implemented to deal properly with the LSM security features of +the Linux kernel and the SELinux facility. + +One of the problems that CacheFiles faces is that it is generally acting on +behalf of a process, and running in that process's context, and that includes a +security context that is not appropriate for accessing the cache - either +because the files in the cache are inaccessible to that process, or because if +the process creates a file in the cache, that file may be inaccessible to other +processes. + +The way CacheFiles works is to temporarily change the security context (fsuid, +fsgid and actor security label) that the process acts as - without changing the +security context of the process when it the target of an operation performed by +some other process (so signalling and suchlike still work correctly). + + +When the CacheFiles module is asked to bind to its cache, it: + + (1) Finds the security label attached to the root cache directory and uses + that as the security label with which it will create files. By default, + this is: + + cachefiles_var_t + + (2) Finds the security label of the process which issued the bind request + (presumed to be the cachefilesd daemon), which by default will be: + + cachefilesd_t + + and asks LSM to supply a security ID as which it should act given the + daemon's label. By default, this will be: + + cachefiles_kernel_t + + SELinux transitions the daemon's security ID to the module's security ID + based on a rule of this form in the policy. + + type_transition <daemon's-ID> kernel_t : process <module's-ID>; + + For instance: + + type_transition cachefilesd_t kernel_t : process cachefiles_kernel_t; + + +The module's security ID gives it permission to create, move and remove files +and directories in the cache, to find and access directories and files in the +cache, to set and access extended attributes on cache objects, and to read and +write files in the cache. + +The daemon's security ID gives it only a very restricted set of permissions: it +may scan directories, stat files and erase files and directories. It may +not read or write files in the cache, and so it is precluded from accessing the +data cached therein; nor is it permitted to create new files in the cache. + + +There are policy source files available in: + + http://people.redhat.com/~dhowells/fscache/cachefilesd-0.8.tar.bz2 + +and later versions. In that tarball, see the files: + + cachefilesd.te + cachefilesd.fc + cachefilesd.if + +They are built and installed directly by the RPM. + +If a non-RPM based system is being used, then copy the above files to their own +directory and run: + + make -f /usr/share/selinux/devel/Makefile + semodule -i cachefilesd.pp + +You will need checkpolicy and selinux-policy-devel installed prior to the +build. + + +By default, the cache is located in /var/fscache, but if it is desirable that +it should be elsewhere, than either the above policy files must be altered, or +an auxiliary policy must be installed to label the alternate location of the +cache. + +For instructions on how to add an auxiliary policy to enable the cache to be +located elsewhere when SELinux is in enforcing mode, please see: + + /usr/share/doc/cachefilesd-*/move-cache.txt + +When the cachefilesd rpm is installed; alternatively, the document can be found +in the sources.
fs/Kconfig +1 -0
@@ -659,6 +659,7 @@ config GENERIC_ACL menu "Caches" source "fs/fscache/Kconfig" +source "fs/cachefiles/Kconfig" endmenu
fs/Makefile +1 -0
@@ -116,6 +116,7 @@ obj-$(CONFIG_AFS_FS) += afs/ obj-$(CONFIG_BEFS_FS) += befs/ obj-$(CONFIG_HOSTFS) += hostfs/ obj-$(CONFIG_HPPFS) += hppfs/ +obj-$(CONFIG_CACHEFILES) += cachefiles/ obj-$(CONFIG_DEBUG_FS) += debugfs/ obj-$(CONFIG_OCFS2_FS) += ocfs2/ obj-$(CONFIG_GFS2_FS) += gfs2/
fs/cachefiles/Kconfig new file +33 -0
@@ -0,0 +1,33 @@ + +config CACHEFILES + tristate "Filesystem caching on files" + depends on FSCACHE + help + This permits use of a mounted filesystem as a cache for other + filesystems - primarily networking filesystems - thus allowing fast + local disk to enhance the speed of slower devices. + + See Documentation/filesystems/caching/cachefiles.txt for more + information. + +config CACHEFILES_DEBUG + bool "Debug CacheFiles" + depends on CACHEFILES + help + This permits debugging to be dynamically enabled in the filesystem + caching on files module. If this is set, the debugging output may be + enabled by setting bits in /sys/modules/cachefiles/parameter/debug or + by including a debugging specifier in /etc/cachefilesd.conf. + +config CACHEFILES_HISTOGRAM + bool "Gather latency information on CacheFiles" + depends on CACHEFILES && FSCACHE_PROC + help + + This option causes latency information to be gathered on CacheFiles + operation and exported through file: + + /proc/fs/fscache/cachefiles/histogram + + See Documentation/filesystems/caching/cachefiles.txt for more + information.
fs/cachefiles/Makefile new file +18 -0
@@ -0,0 +1,18 @@ +# +# Makefile for caching in a mounted filesystem +# + +cachefiles-y := \ + cf-bind.o \ + cf-daemon.o \ + cf-interface.o \ + cf-key.o \ + cf-main.o \ + cf-namei.o \ + cf-rdwr.o \ + cf-security.o \ + cf-xattr.o + +cachefiles-$(CONFIG_CACHEFILES_HISTOGRAM) += cf-proc.o + +obj-$(CONFIG_CACHEFILES) := cachefiles.o
fs/cachefiles/cf-bind.c new file +289 -0
289 lines not on this page · raw message
fs/cachefiles/cf-daemon.c new file +754 -0
754 lines not on this page · raw message
fs/cachefiles/cf-interface.c new file +445 -0
445 lines not on this page · raw message
fs/cachefiles/cf-internal.h new file +373 -0
373 lines not on this page · raw message
fs/cachefiles/cf-key.c new file +159 -0
159 lines not on this page · raw message
fs/cachefiles/cf-main.c new file +108 -0
108 lines not on this page · raw message
fs/cachefiles/cf-namei.c new file +739 -0
412 lines not on this page · raw message
fs/cachefiles/cf-proc.c new file +166 -0
166 lines not on this page · raw message
fs/cachefiles/cf-rdwr.c new file +851 -0
851 lines not on this page · raw message
fs/cachefiles/cf-security.c new file +105 -0
105 lines not on this page · raw message
fs/cachefiles/cf-xattr.c new file +292 -0
292 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
David Howells
maintainerPATCH 22/26 NFS: Fix memory leak
In reply to David HowellsFix a memory leak whereby multiple clientaddr=xxx mount options just overwrite the duplicated client_address option pointer, without freeing the old memory.
---
fs/nfs/super.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
fs/nfs/super.c +1 -0
@@ -936,6 +936,7 @@ static int nfs_parse_mount_options(char *raw, string =match_strdup (args);if (string ==NULL ) goto out_nomem; +kfree (mnt->client_address); mnt->client_address = string;break ;case Opt_mountaddr:
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 23/26 NFS: Use local caching
In reply to David HowellsThe attached patch makes it possible for the NFS filesystem to make use of the network filesystem local caching service (FS-Cache).
To be able to use this, an updated mount program is required. This can be obtained from:
http://people.redhat.com/steved/fscache/util-linux/
To mount an NFS filesystem to use caching, add an "fsc" option to the mount:
mount warthog:/ /a -o fsc
---
fs/nfs/Makefile | 1 fs/nfs/client.c | 5 + fs/nfs/file.c | 37 ++++ fs/nfs/fscache-def.c | 289 +++++++++++++++++++++++++++++++++ fs/nfs/fscache.c | 391 +++++++++++++++++++++++++++++++++++++++++++++ fs/nfs/fscache.h | 148 +++++++++++++++++ fs/nfs/inode.c | 47 +++++ fs/nfs/read.c | 28 +++ fs/nfs/super.c | 3 fs/nfs/sysctl.c | 1 include/linux/nfs_fs.h | 9 + include/linux/nfs_fs_sb.h | 18 ++ 12 files changed, 968 insertions(+), 9 deletions(-) create mode 100644 fs/nfs/fscache-def.c create mode 100644 fs/nfs/fscache.c create mode 100644 fs/nfs/fscache.h
fs/nfs/Makefile +1 -0
@@ -16,3 +16,4 @@ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ nfs4namespace.o nfs-$(CONFIG_NFS_DIRECTIO) += direct.o nfs-$(CONFIG_SYSCTL) += sysctl.o +nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-def.o
fs/nfs/client.c +5 -0
@@ -43,6 +43,7 @@#include "delegation.h" #include "iostat.h" #include "internal.h" +#include "fscache.h" #define NFSDBG_FACILITY NFSDBG_CLIENT
@@ -139,6 +140,8 @@ static struct nfs_client *nfs_alloc_client(const char *hostname, clp->cl_state =1 <<NFS4CLNT_LEASE_EXPIRED ;#endif +nfs_fscache_get_client_cookie (clp); +return clp; error_3:
@@ -170,6 +173,8 @@ static void nfs_free_client(struct nfs_client *clp)nfs4_shutdown_client (clp); +nfs_fscache_release_client_cookie (clp); +/* -EIO all pending I/O */ if (!IS_ERR (clp->cl_rpcclient))rpc_shutdown_client (clp->cl_rpcclient);
fs/nfs/file.c +36 -1
@@ -35,6 +35,7 @@#include "delegation.h" #include "internal.h" #include "iostat.h" +#include "fscache.h" #define NFSDBG_FACILITY NFSDBG_FILE
@@ -352,22 +353,48 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,return status <0 ? status : copied; } +/* +* Partially or wholly invalidate a page +* - Release the private state associated with a page if undergoing complete +* page invalidation +* - Called if either PG_private or PG_fscache set on the page +* - Caller holds page lock +*/ static void nfs_invalidate_page (struct page *page,unsigned long offset) {if (offset !=0 )return ;/* Cancel any unstarted writes on this page */ nfs_wb_page_cancel (page->mapping->host, page); + +nfs_fscache_invalidate_page (page, page->mapping->host); } +/* +* Release the private state associated with a page +* - Called if either PG_private or PG_fscache set on the page +* - Caller holds page lock +* - Return true (may release) or false (may not) +*/ static int nfs_release_page (struct page *page,gfp_t gfp) {/* If PagePrivate() is set, then the page is not freeable */ -return 0 ; +if (PagePrivate (page)) +return 0 ; +return nfs_fscache_release_page (page, gfp); } +/* +* Attempt to clear the private state associated with a page when an error +* occurs that requires the cached contents of an inode to be written back or +* destroyed +* - Called if either PG_private or PG_fscache set on the page +* - Caller holds page lock +* - Return 0 if successful, -error otherwise +*/ static int nfs_launder_page (struct page *page) { +wait_on_page_fscache_write (page);return nfs_wb_page (page->mapping->host, page); }
@@ -387,6 +414,11 @@ const struct address_space_operations nfs_file_aops = { .launder_page = nfs_launder_page, }; +/* +* Notification that a PTE pointing to an NFS page is about to be made +* writable, implying that someone is about to modify the page through a +* shared-writable mapping +*/ static int nfs_vm_page_mkwrite (struct vm_area_struct *vma,struct page *page) {struct file *filp = vma->vm_file;
@@ -396,6 +428,9 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page)struct address_space *mapping;loff_t offset; +/* make sure the cache has finished storing the page */ +wait_on_page_fscache_write (page); +lock_page (page); mapping = page->mapping;if (mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) {
fs/nfs/fscache-def.c new file +289 -0
289 lines not on this page · raw message
fs/nfs/fscache.c new file +391 -0
391 lines not on this page · raw message
fs/nfs/fscache.h new file +148 -0
148 lines not on this page · raw message
fs/nfs/inode.c +41 -6
142 lines not on this page · raw message
fs/nfs/read.c +26 -2
@@ -18,12 +18,14 @@#include <linux/sunrpc/clnt.h> #include <linux/nfs_fs.h> #include <linux/nfs_page.h> +#include <linux/nfs_mount.h> #include <linux/smp_lock.h> #include <asm/system.h> #include "internal.h" #include "iostat.h" +#include "fscache.h" #define NFSDBG_FACILITY NFSDBG_PAGECACHE
@@ -114,8 +116,8 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data) } } -static int nfs_readpage_async (struct nfs_open_context *ctx,struct inode *inode, -struct page *page) +int nfs_readpage_async (struct nfs_open_context *ctx,struct inode *inode, +struct page *page) {LIST_HEAD (one_request);struct nfs_page *new;
@@ -142,6 +144,11 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,static void nfs_readpage_release (struct nfs_page *req) { +struct inode *d_inode = req->wb_context->path.dentry->d_inode; + +if (PageUptodate (req->wb_page)) +nfs_readpage_to_fscache (d_inode, req->wb_page,0 ); +unlock_page (req->wb_page); dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
@@ -496,8 +503,15 @@ int nfs_readpage(struct file *file, struct page *page) }else ctx =get_nfs_open_context (nfs_file_open_context (file)); +if (!IS_SYNC (inode)) { + error =nfs_readpage_from_fscache (ctx, inode, page); +if (error ==0 ) + goto out; + } + error =nfs_readpage_async (ctx, inode, page); +out:put_nfs_open_context (ctx);return error; out_unlock:
@@ -573,6 +587,15 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,return -EBADF ; }else desc.ctx =get_nfs_open_context (nfs_file_open_context (filp)); + +/* attempt to read as many of the pages as possible from the cache +* - this returns -ENOBUFS immediately if the cookie is negative +*/ + ret =nfs_readpages_from_fscache (desc.ctx, inode, mapping, + pages, &nr_pages); +if (ret ==0 ) + goto read_complete;/* all pages were read */ +if (rsize <PAGE_CACHE_SIZE )nfs_pageio_init (&pgio, inode, nfs_pagein_multi, rsize,0 );else
@@ -583,6 +606,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,nfs_pageio_complete (&pgio); npages = (pgio.pg_bytes_written +PAGE_CACHE_SIZE -1 ) >>PAGE_CACHE_SHIFT ;nfs_add_stats (inode,NFSIOS_READPAGES , npages); +read_complete:put_nfs_open_context (desc.ctx); out:return ret;
fs/nfs/super.c +3 -0
@@ -57,6 +57,7 @@#include "delegation.h" #include "iostat.h" #include "internal.h" +#include "fscache.h" #define NFSDBG_FACILITY NFSDBG_VFS
@@ -549,6 +550,8 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)rpc_print_iostats (m, nfss->client); +nfs_fscache_show_stats (m, nfss); +return 0 ; }
fs/nfs/sysctl.c +1 -0
@@ -14,6 +14,7 @@#include <linux/nfs_fs.h> #include "callback.h" +#include "internal.h" static const int nfs_set_port_min =0 ;static const int nfs_set_port_max =65535 ;
include/linux/nfs_fs.h +9 -0
@@ -174,6 +174,9 @@ struct nfs_inode {int delegation_state;struct rw_semaphore rwsem;#endif /* CONFIG_NFS_V4*/ +#ifdef CONFIG_NFS_FSCACHE +struct fscache_cookie *fscache; +#endif struct inode vfs_inode; };
@@ -187,6 +190,7 @@ struct nfs_inode {#define NFS_INO_INVALID_ACL 0x0010/* cached acls are invalid */ #define NFS_INO_REVAL_PAGECACHE 0x0020/* must revalidate pagecache */ #define NFS_INO_REVAL_FORCED 0x0040/* force revalidation ignoring a delegation */ +#define NFS_INO_INVALID_FSCACHE_ATTR 0x0080/* local cache attributes are invalid */ /* * Bit offsets in flags field
@@ -195,6 +199,7 @@ struct nfs_inode {#define NFS_INO_ADVISE_RDPLUS (1)/* advise readdirplus */ #define NFS_INO_STALE (2)/* possible stale inode */ #define NFS_INO_ACL_LRU_SET (3)/* Inode is on the LRU list */ +#define NFS_INO_FSCACHE (4)/* inode can be cached by FS-Cache */ static inline struct nfs_inode *NFS_I (struct inode *inode) {
@@ -216,6 +221,7 @@ static inline struct nfs_inode *NFS_I(struct inode *inode)#define NFS_FLAGS (inode) (NFS_I(inode)->flags)#define NFS_STALE (inode) (test_bit(NFS_INO_STALE, &NFS_FLAGS(inode))) +#define NFS_FSCACHE (inode) (test_bit(NFS_INO_FSCACHE, &NFS_FLAGS(inode)))#define NFS_FILEID (inode) (NFS_I(inode)->fileid)
@@ -455,6 +461,8 @@ extern int nfs_readpages(struct file *, struct address_space *, struct list_head *, unsigned);extern int nfs_readpage_result (struct rpc_task *,struct nfs_read_data *);extern void nfs_readdata_release (void *data); +extern int nfs_readpage_async (struct nfs_open_context *,struct inode *, +struct page *);/* * Allocate nfs_read_data structures
@@ -545,6 +553,7 @@ extern void * nfs_root_data(void);#define NFSDBG_CALLBACK 0x0100#define NFSDBG_CLIENT 0x0200#define NFSDBG_MOUNT 0x0400 +#define NFSDBG_FSCACHE 0x0800#define NFSDBG_ALL 0xFFFF#ifdef __KERNEL__
include/linux/nfs_fs_sb.h +18 -0
@@ -3,6 +3,7 @@#include <linux/list.h> #include <linux/backing-dev.h> +#include <linux/fscache.h> struct nfs_iostats ;
@@ -65,6 +66,10 @@ struct nfs_client {char cl_ipaddr[16 ];unsigned char cl_id_uniquifier;#endif + +#ifdef CONFIG_NFS_FSCACHE +struct fscache_cookie *fscache;/* client index cache cookie */ +#endif };/*
@@ -95,12 +100,25 @@ struct nfs_server {unsigned int acdirmin;unsigned int acdirmax;unsigned int namelen; +unsigned int options;/* extra options enabled by mount */ +#define NFS_OPTION_FSCACHE 0x00000001/* - local caching enabled */ struct nfs_fsid fsid;__u64 maxfilesize;/* maximum file size */ unsigned long mount_time;/* when this fs was mounted */ dev_t s_dev;/* superblock dev numbers */ +#ifdef CONFIG_NFS_FSCACHE +/* statistical counters for local caching */ +atomic_t fscache_cnt_read_ok; +atomic_t fscache_cnt_read_fail; +atomic_t fscache_cnt_write_ok; +atomic_t fscache_cnt_write_fail; +atomic_t fscache_cnt_uncache; +int fscache_last_read_error; +int fscache_last_write_error; +#endif +#ifdef CONFIG_NFS_V4 u32 attr_bitmask[2 ];/* V4 bitmask representing the set of attributes supported on this
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 24/26 NFS: Configuration and mount option changes to enable local caching on NFS
In reply to David HowellsChanges to the kernel configuration defintions and to the NFS mount options to allow the local caching support added by the previous patch to be enabled.
---
fs/Kconfig | 8 ++++++++ fs/nfs/client.c | 2 ++ fs/nfs/internal.h | 1 + fs/nfs/super.c | 14 ++++++++++++++ 4 files changed, 25 insertions(+), 0 deletions(-)
fs/Kconfig +8 -0
@@ -1650,6 +1650,14 @@ config NFS_V4 If unsure, say N. +config NFS_FSCACHE + bool "Provide NFS client caching support (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on NFS_FS=m && FSCACHE || NFS_FS=y && FSCACHE=y + help + Say Y here if you want NFS data to be cached locally on disc through + the general filesystem cache manager + config NFS_DIRECTIO bool "Allow direct I/O on NFS files" depends on NFS_FS
fs/nfs/client.c +2 -0
@@ -572,6 +572,7 @@ static int nfs_init_server(struct nfs_server *server,/* Initialise the client representation from the mount data */ server->flags = data->flags &NFS_MOUNT_FLAGMASK ; + server->options = data->options;if (data->rsize) server->rsize =nfs_block_size (data->rsize,NULL );
@@ -931,6 +932,7 @@ static int nfs4_init_server(struct nfs_server *server,/* Initialise the client representation from the mount data */ server->flags = data->flags &NFS_MOUNT_FLAGMASK ; server->caps |=NFS_CAP_ATOMIC_OPEN ; + server->options = data->options;if (data->rsize) server->rsize =nfs_block_size (data->rsize,NULL );
fs/nfs/internal.h +1 -0
@@ -35,6 +35,7 @@ struct nfs_parsed_mount_data {int acregmin, acregmax, acdirmin, acdirmax;int namlen; +unsigned int options;unsigned int bsize;unsigned int auth_flavor_len;rpc_authflavor_t auth_flavors[1 ];
fs/nfs/super.c +14 -0
@@ -74,6 +74,7 @@ enum { Opt_acl, Opt_noacl, Opt_rdirplus, Opt_nordirplus, Opt_sharecache, Opt_nosharecache, + Opt_fscache, Opt_nofscache,/* Mount options that take integer arguments */ Opt_port,
@@ -123,6 +124,8 @@ static match_table_t nfs_mount_option_tokens = { { Opt_nordirplus, "nordirplus" }, { Opt_sharecache, "sharecache" }, { Opt_nosharecache, "nosharecache" }, + { Opt_fscache, "fsc" }, + { Opt_nofscache, "nofsc" }, { Opt_port, "port=%u" }, { Opt_rsize, "rsize=%u" },
@@ -459,6 +462,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,seq_printf (m,",timeo=%lu" ,10U * clp->retrans_timeo /HZ );seq_printf (m,",retrans=%u" , clp->retrans_count);seq_printf (m,",sec=%s" ,nfs_pseudoflavour_to_name (nfss->client->cl_auth->au_flavor)); +if (nfss->options &NFS_OPTION_FSCACHE ) +seq_printf (m,",fsc" ); }/*
@@ -697,6 +702,15 @@ static int nfs_parse_mount_options(char *raw,break ;case Opt_nosharecache: mnt->flags |=NFS_MOUNT_UNSHARED ; + mnt->options &= ~NFS_OPTION_FSCACHE ; +break ; +case Opt_fscache: +/* sharing is mandatory with fscache */ + mnt->options |=NFS_OPTION_FSCACHE ; + mnt->flags &= ~NFS_MOUNT_UNSHARED ; +break ; +case Opt_nofscache: + mnt->options &= ~NFS_OPTION_FSCACHE ;break ;case Opt_port:
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 25/26 NFS: Display local caching state
In reply to David HowellsDisplay the local caching state in /proc/fs/nfsfs/volumes.
---
fs/nfs/client.c | 7 ++++--- fs/nfs/fscache.h | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-)
fs/nfs/client.c +4 -3
@@ -1335,7 +1335,7 @@ static int nfs_volume_list_show(struct seq_file *m, void *v)/* display header on line 1 */ if (v == &nfs_volume_list) { -seq_puts (m,"NV SERVER PORT DEV FSID\n" ); +seq_puts (m,"NV SERVER PORT DEV FSID FSC\n" );return 0 ; }/* display one transport per line on subsequent lines */
@@ -1349,12 +1349,13 @@ static int nfs_volume_list_show(struct seq_file *m, void *v) (unsigned long long ) server->fsid.major, (unsigned long long) server->fsid.minor); -seq_printf (m,"v%d %02x%02x%02x%02x %4hx %-7s %-17s\n" , +seq_printf (m,"v%d %02x%02x%02x%02x %4hx %-7s %-17s %s\n" , clp->cl_nfsversion,NIPQUAD (clp->cl_addr.sin_addr),ntohs (clp->cl_addr.sin_port), dev, - fsid); + fsid, +nfs_server_fscache_state (server));return 0 ; }
fs/nfs/fscache.h +15 -0
@@ -53,6 +53,17 @@ extern void __nfs_fscache_invalidate_page(struct page *, struct inode *);extern int nfs_fscache_release_page (struct page *,gfp_t );/* +* indicate the client caching state as readable text +*/ +static inline const char *nfs_server_fscache_state (struct nfs_server *server) +{ +if (server->nfs_client->fscache && + (server->options &NFS_OPTION_FSCACHE )) +return "yes" ; +return "no " ; +} + +/* * release the caching state associated with a page if undergoing complete page * invalidation */
@@ -109,6 +120,10 @@ static inline void nfs4_fscache_get_client_cookie(struct nfs_client *clp) {}static inline void nfs_fscache_release_client_cookie (struct nfs_client *clp) {}static inline void nfs_fscache_show_stats (struct seq_file *m,struct nfs_server *nfss) {} +static inline const char *nfs_server_fscache_state (struct nfs_server *server) +{ +return "no " ; +}static inline void nfs_fscache_init_fh_cookie (struct inode *inode) {}static inline void nfs_fscache_enable_fh_cookie (struct inode *inode) {}
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerPATCH 26/26 NFS: Separate caching by superblock, explicitly if necessary
In reply to David HowellsSeparate caching by superblock, explicitly if necessary. This means mounts of the same remote data with different parameters do not share cache objects for common files. The administrator may also provide a uniquifier to further enhance the uniqueness.
Where it is otherwise impossible to distinguish superblocks because all the parameters are identical, but the 'nosharecache' option is supplied, a uniquifying string must be supplied, else only the first mount will be permitted to use the cache.
If there's a key collision, then the second mount will disable caching and give a warning into the kernel log.
There are three variant NFS mount options that can be added to a mount command to control caching for a mount. Only the last one specified takes effect:
(*) Adding "fsc" will request caching.
(*) Adding "fsc=<string>" will request caching and also specify a uniquifier.
(*) Adding "nofsc" will disable caching.
---
fs/nfs/fscache-def.c | 33 ++++++++++++ fs/nfs/fscache.c | 122 ++++++++++++++++++++++++++++++++++++++++++++- fs/nfs/fscache.h | 46 ++++++++++++++++- fs/nfs/internal.h | 3 + fs/nfs/super.c | 24 +++++++-- include/linux/nfs_fs_sb.h | 3 + 6 files changed, 220 insertions(+), 11 deletions(-)
fs/nfs/fscache-def.c +33 -0
@@ -117,6 +117,39 @@ const struct fscache_cookie_def nfs_cache_server_index_def = { };/* +* Generate a key to describe a superblock key in the main NFS index +*/ +static uint16_t nfs_super_get_key (const void *cookie_netfs_data, +void *buffer,uint16_t bufmax) +{ +const struct nfs_fscache_key *key; +const struct nfs_server *nfss = cookie_netfs_data; +uint16_t len; + + key = nfss->fscache_key; + len =sizeof (key->key) + key->key.uniq_len; +if (len > bufmax) { + len =0 ; + }else { +memcpy (buffer, &key->key,sizeof (key->key)); +memcpy (buffer +sizeof (key->key), + key->key.uniquifier, key->key.uniq_len); + } + +return len; +} + +/* +* The superblock index for the filesystem is defined by all the NFS parameters +* that might cause a separate superblock +*/ +const struct fscache_cookie_def nfs_cache_super_index_def = { + .name ="NFS.supers" , + .type =FSCACHE_COOKIE_TYPE_INDEX , + .get_key = nfs_super_get_key, +}; + +/* * Generate a key to describe an NFS inode in an NFS server's index */ static uint16_t nfs_fh_get_key(const void *cookie_netfs_data,
fs/nfs/fscache.c +118 -4
140 lines not on this page · raw message
fs/nfs/fscache.h +44 -2
74 lines not on this page · raw message
fs/nfs/internal.h +3 -0
@@ -4,6 +4,8 @@#include <linux/mount.h> +#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS) +struct nfs_string ;/* Maximum number of readahead requests
@@ -40,6 +42,7 @@ struct nfs_parsed_mount_data {unsigned int auth_flavor_len;rpc_authflavor_t auth_flavors[1 ];char *client_address; +char *fscache_uniq;struct {struct sockaddr_in address;
fs/nfs/super.c +19 -5
@@ -91,6 +91,7 @@ enum {/* Mount options that take string arguments */ Opt_sec, Opt_proto, Opt_mountproto, Opt_addr, Opt_mountaddr, Opt_clientaddr, + Opt_fscache_uniq,/* Mount options that are ignored */ Opt_userspace, Opt_deprecated,
@@ -125,6 +126,7 @@ static match_table_t nfs_mount_option_tokens = { { Opt_sharecache, "sharecache" }, { Opt_nosharecache, "nosharecache" }, { Opt_fscache, "fsc" }, + { Opt_fscache_uniq, "fsc=%s" }, { Opt_nofscache, "nofsc" }, { Opt_port, "port=%u" },
@@ -702,15 +704,24 @@ static int nfs_parse_mount_options(char *raw,break ;case Opt_nosharecache: mnt->flags |=NFS_MOUNT_UNSHARED ; - mnt->options &= ~NFS_OPTION_FSCACHE ;break ;case Opt_fscache: -/* sharing is mandatory with fscache */ mnt->options |=NFS_OPTION_FSCACHE ; - mnt->flags &= ~NFS_MOUNT_UNSHARED ; +kfree (mnt->fscache_uniq); + mnt->fscache_uniq =NULL ;break ;case Opt_nofscache: mnt->options &= ~NFS_OPTION_FSCACHE ; +kfree (mnt->fscache_uniq); + mnt->fscache_uniq =NULL ; +break ; +case Opt_fscache_uniq: + string =match_strdup (args); +if (!string) + goto out_nomem; +kfree (mnt->fscache_uniq); + mnt->fscache_uniq = string; + mnt->options |=NFS_OPTION_FSCACHE ;break ;case Opt_port:
@@ -1288,8 +1299,6 @@ static void nfs_clone_super(struct super_block *sb,nfs_initialise_sb (sb); } -#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS) -static int nfs_compare_mount_options (const struct super_block *s,const struct nfs_server *b,int flags) {const struct nfs_server *a = s->s_fs_info;
@@ -1403,6 +1412,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,if (!s->s_root) {/* initial superblock/root creation */ nfs_fill_super (s, &data); +nfs_fscache_get_super_cookie (s, &data); } mntroot =nfs_get_root (s, &mntfh);
@@ -1418,6 +1428,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, out:kfree (data.nfs_server.hostname); +kfree (data.fscache_uniq);return error; out_err_nosb:
@@ -1438,6 +1449,7 @@ static void nfs_kill_super(struct super_block *s)struct nfs_server *server =NFS_SB (s);kill_anon_super (s); +nfs_fscache_release_super_cookie (s);nfs_free_server (server); }
@@ -1752,6 +1764,7 @@ static int nfs4_get_sb(struct file_system_type *fs_type,if (!s->s_root) {/* initial superblock/root creation */ nfs4_fill_super (s); +nfs_fscache_get_super_cookie (s, &data); } mntroot =nfs4_get_root (s, &mntfh);
@@ -1769,6 +1782,7 @@ out:kfree (data.client_address);kfree (data.nfs_server.export_path);kfree (data.nfs_server.hostname); +kfree (data.fscache_uniq);return error; out_free:
include/linux/nfs_fs_sb.h +3 -0
@@ -109,6 +109,9 @@ struct nfs_server {dev_t s_dev;/* superblock dev numbers */ #ifdef CONFIG_NFS_FSCACHE +struct nfs_fscache_key *fscache_key;/* unique key for superblock */ +struct fscache_cookie *fscache;/* superblock cookie */ +/* statistical counters for local caching */ atomic_t fscache_cnt_read_ok;atomic_t fscache_cnt_read_fail;
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
James Morris
maintainerQuoted 4 lines · David Howells
The SELinux base code will also need updating to have the security class, lest the following error appear in dmesg:
context_struct_compute_av: unrecognized class 69
Alternately, what's needed is a newer policy which supports unknown permission classes. Any recent distro policy should have this.
- James
Signature · 7 lines
James Morris <[email protected]> -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
David Howells
maintainerQuoted 7 lines · James Morris
Quoted 4 lines
The SELinux base code will also need updating to have the security class, lest the following error appear in dmesg:
context_struct_compute_av: unrecognized class 69Alternately, what's needed is a newer policy which supports unknown permission classes. Any recent distro policy should have this.
I'm seeing this with an up to date Fedora 7 installation. Do I need F8 instead?
David
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
James Morris
maintainerQuoted 6 lines · David Howells
(*) 04-keys-get-label.diff
A patch to allow the security label of a key to be retrieved. Included because of patches 05-08.
Quoted 7 lines
(*) 05-security-current-fsugid.diff
(*) 06-security-separate-task-bits.diff
(*) 07-security-subjective.diff
(*) 08-security-secctx2secid.diff
(*) 09-security-additional-classes.diff
(*) 10-security-kernel_service-class.diff
(*) 11-security-kernel-service.diff
All of the security patches look ok to me. From the SELinux pov, this will need to go in after Paul Moore's labeled networking update (hopefully very soon after the next merge window opens).
- James
Signature · 7 lines
James Morris <[email protected]> -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 3 lines · David Howells
(*) 01-keys-inc-payload.diff
(*) 02-keys-search-keyring.diff
(*) 03-keys-callout-blob.diff
One vaguely related question: Is there presently any way to adjust the per-user max-key-data limit? I've been tinkering with using the new-ish MIT kerberos "KEYRING:" credentials-cache code to hold keys for persistent daemons. Unfortunately "root" keeps hitting the limit even with only about 16 keys allocated across a few sessions. After perusing the docs I can't find any documentation on adjusting the limits.
I'd really like some way to specifically allow root to allocate up to several megs worth of non-swappable key data, although I suppose just increasing the global limit slightly wouldn't be bad either. If such functionality already exists then I'd appreciate a pointer to it (and possibly respond in kind with documentation patches).
Cheers,
Kyle Moffett
David Howells
maintainerQuoted 2 lines · Kyle Moffett
One vaguely related question: Is there presently any way to adjust the per-user max-key-data limit?
There's no reason there can't be. It just needs a policy deciding. Do we have:
(1) One control for all.
(2) One control for all non-root users; no quotas on root.
(3) One control for root, one control for all non-root users.
(3) Separate controls for all users.
Should this be a ulimit? Should a non-root user be able to adjust their own quotas within limits set by root?
How should the quota be accessed? The obvious way is to have /proc or /sys controls.
Non-root quotas tend to be transitory. When the user_struct pinning them goes out of scope, they tend to disappear. How do we recover the settings, if at all?
David
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
A message that is not in the archive (sent off-list or not yet received): 20080115234724.22183.9603.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org
David Howells
maintainerPATCH 1/1 Security: Make NFSD work with detached security
Make NFSD work with detached security, using the patches that excise the security information from task_struct to struct task_security as a base.
Each time NFSD wants a new security descriptor (to do NFS4 recovery or just to do NFS operations), a task_security record is derived from NFSD's *objective* security, modified and then applied as the *subjective* security. This means
(a) the changes are not visible to anyone looking at NFSD through /proc, (b) there is no leakage between two consecutive ops with different security configurations.
Consideration should probably be given to caching the task_security record on the basis that there'll probably be several ops that will want to use any particular security configuration.
Furthermore, nfs4recover.c perhaps ought to set an appropriate LSM context on the record pointed to by rec_security so that the disk is accessed appropriately (see set_security_override[_from_ctx]()).
NOTE! This patch must be and will be rolled in to patch 06 of 26 to make the latter compile fully, however it may be useful to the nfsd maintainers to see it as a separate patch.
---
fs/nfsd/auth.c | 31 +++++++++++++++++------- fs/nfsd/nfs4recover.c | 64 +++++++++++++++++++++++++++++++------------------ include/linux/sched.h | 1 + kernel/sys.c | 27 ++++++++++++++++++--- 4 files changed, 86 insertions(+), 37 deletions(-)
fs/nfsd/auth.c +22 -9
@@ -6,6 +6,7 @@#include <linux/types.h> #include <linux/sched.h> +#include <linux/cred.h> #include <linux/sunrpc/svc.h> #include <linux/sunrpc/svcauth.h> #include <linux/nfsd/nfsd.h>
@@ -28,11 +29,17 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)int nfsd_setuser (struct svc_rqst *rqstp,struct svc_export *exp) { +struct task_security *sec, *old;struct svc_cred cred = rqstp->rq_cred;int i;int flags =nfsexp_flags (rqstp, exp);int ret; +/* derive the new security record from nfsd's objective security */ + sec =get_kernel_security (current); +if (!sec) +return -ENOMEM ; +if (flags &NFSEXP_ALLSQUASH ) { cred.cr_uid = exp->ex_anon_uid; cred.cr_gid = exp->ex_anon_gid;
@@ -56,23 +63,29 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)get_group_info (cred.cr_group_info);if (cred.cr_uid != (uid_t) -1 ) - current->fsuid = cred.cr_uid; + sec->fsuid = cred.cr_uid;else - current->fsuid = exp->ex_anon_uid; + sec->fsuid = exp->ex_anon_uid;if (cred.cr_gid != (gid_t) -1 ) - current->fsgid = cred.cr_gid; + sec->fsgid = cred.cr_gid;else - current->fsgid = exp->ex_anon_gid; + sec->fsgid = exp->ex_anon_gid; -if (!cred.cr_group_info) +if (!cred.cr_group_info) { +put_task_security (sec);return -ENOMEM ; - ret =set_current_groups (cred.cr_group_info); + } + ret =set_groups (sec, cred.cr_group_info);put_group_info (cred.cr_group_info);if ((cred.cr_uid)) { -cap_t (current->cap_effective) &= ~CAP_NFSD_MASK ; +cap_t (sec->cap_effective) &= ~CAP_NFSD_MASK ; }else { -cap_t (current->cap_effective) |= (CAP_NFSD_MASK & - current->cap_permitted); +cap_t (sec->cap_effective) |=CAP_NFSD_MASK & sec->cap_permitted; } + +/* set the new security as nfsd's subjective security */ + old = current->act_as; + current->act_as = sec; +put_task_security (old);return ret; }
fs/nfsd/nfs4recover.c +40 -24
161 lines not on this page · raw message
include/linux/sched.h +1 -0
@@ -886,6 +886,7 @@ struct group_info {extern struct group_info *groups_alloc (int gidsetsize);extern void groups_free (struct group_info *group_info);extern int set_current_groups (struct group_info *group_info); +extern int set_groups (struct task_security *sec,struct group_info *group_info);extern int groups_search (struct group_info *group_info,gid_t grp);/* access the groups "array" with this macro */ #define GROUP_AT (gi, i) \
kernel/sys.c +23 -4
@@ -1245,10 +1245,16 @@ int groups_search(struct group_info *group_info, gid_t grp)return 0 ; } -/* validate and set current->group_info */ -int set_current_groups (struct group_info *group_info) +/** +* set_groups - Change a group subscription in a security record +* @sec: The security record to alter +* @group_info: The group list to impose +* +* Validate a group subscription and, if valid, impose it upon a task security +* record. +*/ +int set_groups (struct task_security *sec,struct group_info *group_info) { -struct task_security *sec = current->sec;int retval;struct group_info *old_info;
@@ -1265,10 +1271,23 @@ int set_current_groups(struct group_info *group_info)spin_unlock (&sec->lock);put_group_info (old_info); -return 0 ; } +EXPORT_SYMBOL (set_groups); + +/** +* set_current_groups - Change current's group subscription +* @group_info: The group list to impose +* +* Validate a group subscription and, if valid, impose it upon current's task +* security record. +*/ +int set_current_groups (struct group_info *group_info) +{ +return set_groups (current->sec, group_info); +} +EXPORT_SYMBOL (set_current_groups);asmlinkage long sys_getgroups (int gidsetsize,gid_t __user *grouplist)
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs
_______________________________________________
Please note that [email protected] is being discontinued. Please subscribe to [email protected] instead.
http://vger.kernel.org/vger-lists.html#linux-nfs