提交 434d42cf 编写于 作者: J James Morris

Merge branch 'next' into for-linus

...@@ -820,6 +820,8 @@ static int load_flat_shared_library(int id, struct lib_info *libs) ...@@ -820,6 +820,8 @@ static int load_flat_shared_library(int id, struct lib_info *libs)
int res; int res;
char buf[16]; char buf[16];
memset(&bprm, 0, sizeof(bprm));
/* Create the file name */ /* Create the file name */
sprintf(buf, "/lib/lib%d.so", id); sprintf(buf, "/lib/lib%d.so", id);
...@@ -835,6 +837,12 @@ static int load_flat_shared_library(int id, struct lib_info *libs) ...@@ -835,6 +837,12 @@ static int load_flat_shared_library(int id, struct lib_info *libs)
if (!bprm.cred) if (!bprm.cred)
goto out; goto out;
/* We don't really care about recalculating credentials at this point
* as we're past the point of no return and are dealing with shared
* libraries.
*/
bprm.cred_prepared = 1;
res = prepare_binprm(&bprm); res = prepare_binprm(&bprm);
if (!IS_ERR_VALUE(res)) if (!IS_ERR_VALUE(res))
......
...@@ -417,7 +417,6 @@ extern const kernel_cap_t __cap_init_eff_set; ...@@ -417,7 +417,6 @@ extern const kernel_cap_t __cap_init_eff_set;
# define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }}) # define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }})
# define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }}) # define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }})
# define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }})
# define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ # define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \
| CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \ | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \
CAP_FS_MASK_B1 } }) CAP_FS_MASK_B1 } })
...@@ -427,11 +426,7 @@ extern const kernel_cap_t __cap_init_eff_set; ...@@ -427,11 +426,7 @@ extern const kernel_cap_t __cap_init_eff_set;
#endif /* _KERNEL_CAPABILITY_U32S != 2 */ #endif /* _KERNEL_CAPABILITY_U32S != 2 */
#define CAP_INIT_INH_SET CAP_EMPTY_SET
# define cap_clear(c) do { (c) = __cap_empty_set; } while (0) # define cap_clear(c) do { (c) = __cap_empty_set; } while (0)
# define cap_set_full(c) do { (c) = __cap_full_set; } while (0)
# define cap_set_init_eff(c) do { (c) = __cap_init_eff_set; } while (0)
#define cap_raise(c, flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag)) #define cap_raise(c, flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag))
#define cap_lower(c, flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag)) #define cap_lower(c, flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag))
......
...@@ -83,13 +83,6 @@ extern struct group_info init_groups; ...@@ -83,13 +83,6 @@ extern struct group_info init_groups;
#define INIT_IDS #define INIT_IDS
#endif #endif
/*
* Because of the reduced scope of CAP_SETPCAP when filesystem
* capabilities are in effect, it is safe to allow CAP_SETPCAP to
* be available in the default configuration.
*/
# define CAP_INIT_BSET CAP_FULL_SET
#ifdef CONFIG_RCU_BOOST #ifdef CONFIG_RCU_BOOST
#define INIT_TASK_RCU_BOOST() \ #define INIT_TASK_RCU_BOOST() \
.rcu_boost_mutex = NULL, .rcu_boost_mutex = NULL,
......
...@@ -276,6 +276,19 @@ static inline key_serial_t key_serial(struct key *key) ...@@ -276,6 +276,19 @@ static inline key_serial_t key_serial(struct key *key)
return key ? key->serial : 0; return key ? key->serial : 0;
} }
/**
* key_is_instantiated - Determine if a key has been positively instantiated
* @key: The key to check.
*
* Return true if the specified key has been positively instantiated, false
* otherwise.
*/
static inline bool key_is_instantiated(const struct key *key)
{
return test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
!test_bit(KEY_FLAG_NEGATIVE, &key->flags);
}
#define rcu_dereference_key(KEY) \ #define rcu_dereference_key(KEY) \
(rcu_dereference_protected((KEY)->payload.rcudata, \ (rcu_dereference_protected((KEY)->payload.rcudata, \
rwsem_is_locked(&((struct key *)(KEY))->sem))) rwsem_is_locked(&((struct key *)(KEY))->sem)))
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/sysctl.h>
#define KMOD_PATH_LEN 256 #define KMOD_PATH_LEN 256
...@@ -109,6 +110,8 @@ call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait) ...@@ -109,6 +110,8 @@ call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)
NULL, NULL, NULL); NULL, NULL, NULL);
} }
extern struct ctl_table usermodehelper_table[];
extern void usermodehelper_init(void); extern void usermodehelper_init(void);
extern int usermodehelper_disable(void); extern int usermodehelper_disable(void);
......
...@@ -22,12 +22,8 @@ ...@@ -22,12 +22,8 @@
*/ */
const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET; const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET;
const kernel_cap_t __cap_full_set = CAP_FULL_SET;
const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET;
EXPORT_SYMBOL(__cap_empty_set); EXPORT_SYMBOL(__cap_empty_set);
EXPORT_SYMBOL(__cap_full_set);
EXPORT_SYMBOL(__cap_init_eff_set);
int file_caps_enabled = 1; int file_caps_enabled = 1;
......
...@@ -49,10 +49,10 @@ struct cred init_cred = { ...@@ -49,10 +49,10 @@ struct cred init_cred = {
.magic = CRED_MAGIC, .magic = CRED_MAGIC,
#endif #endif
.securebits = SECUREBITS_DEFAULT, .securebits = SECUREBITS_DEFAULT,
.cap_inheritable = CAP_INIT_INH_SET, .cap_inheritable = CAP_EMPTY_SET,
.cap_permitted = CAP_FULL_SET, .cap_permitted = CAP_FULL_SET,
.cap_effective = CAP_INIT_EFF_SET, .cap_effective = CAP_FULL_SET,
.cap_bset = CAP_INIT_BSET, .cap_bset = CAP_FULL_SET,
.user = INIT_USER, .user = INIT_USER,
.user_ns = &init_user_ns, .user_ns = &init_user_ns,
.group_info = &init_groups, .group_info = &init_groups,
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/cred.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/fdtable.h> #include <linux/fdtable.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
...@@ -43,6 +44,13 @@ extern int max_threads; ...@@ -43,6 +44,13 @@ extern int max_threads;
static struct workqueue_struct *khelper_wq; static struct workqueue_struct *khelper_wq;
#define CAP_BSET (void *)1
#define CAP_PI (void *)2
static kernel_cap_t usermodehelper_bset = CAP_FULL_SET;
static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET;
static DEFINE_SPINLOCK(umh_sysctl_lock);
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
/* /*
...@@ -132,6 +140,7 @@ EXPORT_SYMBOL(__request_module); ...@@ -132,6 +140,7 @@ EXPORT_SYMBOL(__request_module);
static int ____call_usermodehelper(void *data) static int ____call_usermodehelper(void *data)
{ {
struct subprocess_info *sub_info = data; struct subprocess_info *sub_info = data;
struct cred *new;
int retval; int retval;
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
...@@ -153,6 +162,19 @@ static int ____call_usermodehelper(void *data) ...@@ -153,6 +162,19 @@ static int ____call_usermodehelper(void *data)
goto fail; goto fail;
} }
retval = -ENOMEM;
new = prepare_kernel_cred(current);
if (!new)
goto fail;
spin_lock(&umh_sysctl_lock);
new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset);
new->cap_inheritable = cap_intersect(usermodehelper_inheritable,
new->cap_inheritable);
spin_unlock(&umh_sysctl_lock);
commit_creds(new);
retval = kernel_execve(sub_info->path, retval = kernel_execve(sub_info->path,
(const char *const *)sub_info->argv, (const char *const *)sub_info->argv,
(const char *const *)sub_info->envp); (const char *const *)sub_info->envp);
...@@ -420,6 +442,84 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, ...@@ -420,6 +442,84 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info,
} }
EXPORT_SYMBOL(call_usermodehelper_exec); EXPORT_SYMBOL(call_usermodehelper_exec);
static int proc_cap_handler(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table t;
unsigned long cap_array[_KERNEL_CAPABILITY_U32S];
kernel_cap_t new_cap;
int err, i;
if (write && (!capable(CAP_SETPCAP) ||
!capable(CAP_SYS_MODULE)))
return -EPERM;
/*
* convert from the global kernel_cap_t to the ulong array to print to
* userspace if this is a read.
*/
spin_lock(&umh_sysctl_lock);
for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++) {
if (table->data == CAP_BSET)
cap_array[i] = usermodehelper_bset.cap[i];
else if (table->data == CAP_PI)
cap_array[i] = usermodehelper_inheritable.cap[i];
else
BUG();
}
spin_unlock(&umh_sysctl_lock);
t = *table;
t.data = &cap_array;
/*
* actually read or write and array of ulongs from userspace. Remember
* these are least significant 32 bits first
*/
err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
if (err < 0)
return err;
/*
* convert from the sysctl array of ulongs to the kernel_cap_t
* internal representation
*/
for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++)
new_cap.cap[i] = cap_array[i];
/*
* Drop everything not in the new_cap (but don't add things)
*/
spin_lock(&umh_sysctl_lock);
if (write) {
if (table->data == CAP_BSET)
usermodehelper_bset = cap_intersect(usermodehelper_bset, new_cap);
if (table->data == CAP_PI)
usermodehelper_inheritable = cap_intersect(usermodehelper_inheritable, new_cap);
}
spin_unlock(&umh_sysctl_lock);
return 0;
}
struct ctl_table usermodehelper_table[] = {
{
.procname = "bset",
.data = CAP_BSET,
.maxlen = _KERNEL_CAPABILITY_U32S * sizeof(unsigned long),
.mode = 0600,
.proc_handler = proc_cap_handler,
},
{
.procname = "inheritable",
.data = CAP_PI,
.maxlen = _KERNEL_CAPABILITY_U32S * sizeof(unsigned long),
.mode = 0600,
.proc_handler = proc_cap_handler,
},
{ }
};
void __init usermodehelper_init(void) void __init usermodehelper_init(void)
{ {
khelper_wq = create_singlethread_workqueue("khelper"); khelper_wq = create_singlethread_workqueue("khelper");
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/pipe_fs_i.h> #include <linux/pipe_fs_i.h>
#include <linux/oom.h> #include <linux/oom.h>
#include <linux/kmod.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -615,6 +616,11 @@ static struct ctl_table kern_table[] = { ...@@ -615,6 +616,11 @@ static struct ctl_table kern_table[] = {
.mode = 0555, .mode = 0555,
.child = random_table, .child = random_table,
}, },
{
.procname = "usermodehelper",
.mode = 0555,
.child = usermodehelper_table,
},
{ {
.procname = "overflowuid", .procname = "overflowuid",
.data = &overflowuid, .data = &overflowuid,
......
...@@ -212,10 +212,12 @@ static void dns_resolver_describe(const struct key *key, struct seq_file *m) ...@@ -212,10 +212,12 @@ static void dns_resolver_describe(const struct key *key, struct seq_file *m)
int err = key->type_data.x[0]; int err = key->type_data.x[0];
seq_puts(m, key->description); seq_puts(m, key->description);
if (err) if (key_is_instantiated(key)) {
seq_printf(m, ": %d", err); if (err)
else seq_printf(m, ": %d", err);
seq_printf(m, ": %u", key->datalen); else
seq_printf(m, ": %u", key->datalen);
}
} }
/* /*
......
...@@ -167,6 +167,7 @@ config INTEL_TXT ...@@ -167,6 +167,7 @@ config INTEL_TXT
config LSM_MMAP_MIN_ADDR config LSM_MMAP_MIN_ADDR
int "Low address space for LSM to protect from user allocation" int "Low address space for LSM to protect from user allocation"
depends on SECURITY && SECURITY_SELINUX depends on SECURITY && SECURITY_SELINUX
default 32768 if ARM
default 65536 default 65536
help help
This is the portion of low virtual memory which should be protected This is the portion of low virtual memory which should be protected
......
...@@ -529,15 +529,10 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) ...@@ -529,15 +529,10 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
new->suid = new->fsuid = new->euid; new->suid = new->fsuid = new->euid;
new->sgid = new->fsgid = new->egid; new->sgid = new->fsgid = new->egid;
/* For init, we want to retain the capabilities set in the initial if (effective)
* task. Thus we skip the usual capability rules new->cap_effective = new->cap_permitted;
*/ else
if (!is_global_init(current)) { cap_clear(new->cap_effective);
if (effective)
new->cap_effective = new->cap_permitted;
else
cap_clear(new->cap_effective);
}
bprm->cap_effective = effective; bprm->cap_effective = effective;
/* /*
......
...@@ -109,11 +109,13 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, ...@@ -109,11 +109,13 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
const struct cred *cred, const struct cred *cred,
struct key_type *type, struct key_type *type,
const void *description, const void *description,
key_match_func_t match); key_match_func_t match,
bool no_state_check);
extern key_ref_t search_my_process_keyrings(struct key_type *type, extern key_ref_t search_my_process_keyrings(struct key_type *type,
const void *description, const void *description,
key_match_func_t match, key_match_func_t match,
bool no_state_check,
const struct cred *cred); const struct cred *cred);
extern key_ref_t search_process_keyrings(struct key_type *type, extern key_ref_t search_process_keyrings(struct key_type *type,
const void *description, const void *description,
......
...@@ -206,8 +206,14 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type, ...@@ -206,8 +206,14 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type,
goto error5; goto error5;
} }
/* wait for the key to finish being constructed */
ret = wait_for_key_construction(key, 1);
if (ret < 0)
goto error6;
ret = key->serial; ret = key->serial;
error6:
key_put(key); key_put(key);
error5: error5:
key_type_put(ktype); key_type_put(ktype);
......
...@@ -176,13 +176,15 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) ...@@ -176,13 +176,15 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m)
else else
seq_puts(m, "[anon]"); seq_puts(m, "[anon]");
rcu_read_lock(); if (key_is_instantiated(keyring)) {
klist = rcu_dereference(keyring->payload.subscriptions); rcu_read_lock();
if (klist) klist = rcu_dereference(keyring->payload.subscriptions);
seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); if (klist)
else seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys);
seq_puts(m, ": empty"); else
rcu_read_unlock(); seq_puts(m, ": empty");
rcu_read_unlock();
}
} }
/* /*
...@@ -271,6 +273,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, ...@@ -271,6 +273,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
* @type: The type of key to search for. * @type: The type of key to search for.
* @description: Parameter for @match. * @description: Parameter for @match.
* @match: Function to rule on whether or not a key is the one required. * @match: Function to rule on whether or not a key is the one required.
* @no_state_check: Don't check if a matching key is bad
* *
* Search the supplied keyring tree for a key that matches the criteria given. * Search the supplied keyring tree for a key that matches the criteria given.
* The root keyring and any linked keyrings must grant Search permission to the * The root keyring and any linked keyrings must grant Search permission to the
...@@ -303,7 +306,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, ...@@ -303,7 +306,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
const struct cred *cred, const struct cred *cred,
struct key_type *type, struct key_type *type,
const void *description, const void *description,
key_match_func_t match) key_match_func_t match,
bool no_state_check)
{ {
struct { struct {
struct keyring_list *keylist; struct keyring_list *keylist;
...@@ -345,6 +349,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, ...@@ -345,6 +349,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
kflags = keyring->flags; kflags = keyring->flags;
if (keyring->type == type && match(keyring, description)) { if (keyring->type == type && match(keyring, description)) {
key = keyring; key = keyring;
if (no_state_check)
goto found;
/* check it isn't negative and hasn't expired or been /* check it isn't negative and hasn't expired or been
* revoked */ * revoked */
...@@ -384,11 +390,13 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, ...@@ -384,11 +390,13 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
continue; continue;
/* skip revoked keys and expired keys */ /* skip revoked keys and expired keys */
if (kflags & (1 << KEY_FLAG_REVOKED)) if (!no_state_check) {
continue; if (kflags & (1 << KEY_FLAG_REVOKED))
continue;
if (key->expiry && now.tv_sec >= key->expiry) if (key->expiry && now.tv_sec >= key->expiry)
continue; continue;
}
/* keys that don't match */ /* keys that don't match */
if (!match(key, description)) if (!match(key, description))
...@@ -399,6 +407,9 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, ...@@ -399,6 +407,9 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
cred, KEY_SEARCH) < 0) cred, KEY_SEARCH) < 0)
continue; continue;
if (no_state_check)
goto found;
/* we set a different error code if we pass a negative key */ /* we set a different error code if we pass a negative key */
if (kflags & (1 << KEY_FLAG_NEGATIVE)) { if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
err = key->type_data.reject_error; err = key->type_data.reject_error;
...@@ -478,7 +489,7 @@ key_ref_t keyring_search(key_ref_t keyring, ...@@ -478,7 +489,7 @@ key_ref_t keyring_search(key_ref_t keyring,
return ERR_PTR(-ENOKEY); return ERR_PTR(-ENOKEY);
return keyring_search_aux(keyring, current->cred, return keyring_search_aux(keyring, current->cred,
type, description, type->match); type, description, type->match, false);
} }
EXPORT_SYMBOL(keyring_search); EXPORT_SYMBOL(keyring_search);
......
...@@ -199,7 +199,7 @@ static int proc_keys_show(struct seq_file *m, void *v) ...@@ -199,7 +199,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
if (key->perm & KEY_POS_VIEW) { if (key->perm & KEY_POS_VIEW) {
skey_ref = search_my_process_keyrings(key->type, key, skey_ref = search_my_process_keyrings(key->type, key,
lookup_user_key_possessed, lookup_user_key_possessed,
cred); true, cred);
if (!IS_ERR(skey_ref)) { if (!IS_ERR(skey_ref)) {
key_ref_put(skey_ref); key_ref_put(skey_ref);
key_ref = make_key_ref(key, 1); key_ref = make_key_ref(key, 1);
......
...@@ -331,6 +331,7 @@ void key_fsgid_changed(struct task_struct *tsk) ...@@ -331,6 +331,7 @@ void key_fsgid_changed(struct task_struct *tsk)
key_ref_t search_my_process_keyrings(struct key_type *type, key_ref_t search_my_process_keyrings(struct key_type *type,
const void *description, const void *description,
key_match_func_t match, key_match_func_t match,
bool no_state_check,
const struct cred *cred) const struct cred *cred)
{ {
key_ref_t key_ref, ret, err; key_ref_t key_ref, ret, err;
...@@ -350,7 +351,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, ...@@ -350,7 +351,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
if (cred->thread_keyring) { if (cred->thread_keyring) {
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(cred->thread_keyring, 1), make_key_ref(cred->thread_keyring, 1),
cred, type, description, match); cred, type, description, match, no_state_check);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -371,7 +372,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, ...@@ -371,7 +372,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
if (cred->tgcred->process_keyring) { if (cred->tgcred->process_keyring) {
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(cred->tgcred->process_keyring, 1), make_key_ref(cred->tgcred->process_keyring, 1),
cred, type, description, match); cred, type, description, match, no_state_check);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -395,7 +396,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, ...@@ -395,7 +396,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
make_key_ref(rcu_dereference( make_key_ref(rcu_dereference(
cred->tgcred->session_keyring), cred->tgcred->session_keyring),
1), 1),
cred, type, description, match); cred, type, description, match, no_state_check);
rcu_read_unlock(); rcu_read_unlock();
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
...@@ -417,7 +418,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, ...@@ -417,7 +418,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
else if (cred->user->session_keyring) { else if (cred->user->session_keyring) {
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(cred->user->session_keyring, 1), make_key_ref(cred->user->session_keyring, 1),
cred, type, description, match); cred, type, description, match, no_state_check);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -459,7 +460,8 @@ key_ref_t search_process_keyrings(struct key_type *type, ...@@ -459,7 +460,8 @@ key_ref_t search_process_keyrings(struct key_type *type,
might_sleep(); might_sleep();
key_ref = search_my_process_keyrings(type, description, match, cred); key_ref = search_my_process_keyrings(type, description, match,
false, cred);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
err = key_ref; err = key_ref;
......
...@@ -530,8 +530,7 @@ struct key *request_key_and_link(struct key_type *type, ...@@ -530,8 +530,7 @@ struct key *request_key_and_link(struct key_type *type,
dest_keyring, flags); dest_keyring, flags);
/* search all the process keyrings for a key */ /* search all the process keyrings for a key */
key_ref = search_process_keyrings(type, description, type->match, key_ref = search_process_keyrings(type, description, type->match, cred);
cred);
if (!IS_ERR(key_ref)) { if (!IS_ERR(key_ref)) {
key = key_ref_to_ptr(key_ref); key = key_ref_to_ptr(key_ref);
......
...@@ -59,7 +59,8 @@ static void request_key_auth_describe(const struct key *key, ...@@ -59,7 +59,8 @@ static void request_key_auth_describe(const struct key *key,
seq_puts(m, "key:"); seq_puts(m, "key:");
seq_puts(m, key->description); seq_puts(m, key->description);
seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); if (key_is_instantiated(key))
seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
} }
/* /*
......
...@@ -157,8 +157,8 @@ EXPORT_SYMBOL_GPL(user_destroy); ...@@ -157,8 +157,8 @@ EXPORT_SYMBOL_GPL(user_destroy);
void user_describe(const struct key *key, struct seq_file *m) void user_describe(const struct key *key, struct seq_file *m)
{ {
seq_puts(m, key->description); seq_puts(m, key->description);
if (key_is_instantiated(key))
seq_printf(m, ": %u", key->datalen); seq_printf(m, ": %u", key->datalen);
} }
EXPORT_SYMBOL_GPL(user_describe); EXPORT_SYMBOL_GPL(user_describe);
......
...@@ -108,10 +108,9 @@ static bool tomoyo_flush(struct tomoyo_io_buffer *head) ...@@ -108,10 +108,9 @@ static bool tomoyo_flush(struct tomoyo_io_buffer *head)
head->read_user_buf += len; head->read_user_buf += len;
w += len; w += len;
} }
if (*w) { head->r.w[0] = w;
head->r.w[0] = w; if (*w)
return false; return false;
}
/* Add '\0' for query. */ /* Add '\0' for query. */
if (head->poll) { if (head->poll) {
if (!head->read_user_buf_avail || if (!head->read_user_buf_avail ||
...@@ -459,8 +458,16 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) ...@@ -459,8 +458,16 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
if (profile == &tomoyo_default_profile) if (profile == &tomoyo_default_profile)
return -EINVAL; return -EINVAL;
if (!strcmp(data, "COMMENT")) { if (!strcmp(data, "COMMENT")) {
const struct tomoyo_path_info *old_comment = profile->comment; static DEFINE_SPINLOCK(lock);
profile->comment = tomoyo_get_name(cp); const struct tomoyo_path_info *new_comment
= tomoyo_get_name(cp);
const struct tomoyo_path_info *old_comment;
if (!new_comment)
return -ENOMEM;
spin_lock(&lock);
old_comment = profile->comment;
profile->comment = new_comment;
spin_unlock(&lock);
tomoyo_put_name(old_comment); tomoyo_put_name(old_comment);
return 0; return 0;
} }
......
...@@ -1011,7 +1011,6 @@ int tomoyo_path_perm(const u8 operation, struct path *path) ...@@ -1011,7 +1011,6 @@ int tomoyo_path_perm(const u8 operation, struct path *path)
break; break;
case TOMOYO_TYPE_RMDIR: case TOMOYO_TYPE_RMDIR:
case TOMOYO_TYPE_CHROOT: case TOMOYO_TYPE_CHROOT:
case TOMOYO_TYPE_UMOUNT:
tomoyo_add_slash(&buf); tomoyo_add_slash(&buf);
break; break;
} }
......
...@@ -75,6 +75,7 @@ void *tomoyo_commit_ok(void *data, const unsigned int size) ...@@ -75,6 +75,7 @@ void *tomoyo_commit_ok(void *data, const unsigned int size)
memset(data, 0, size); memset(data, 0, size);
return ptr; return ptr;
} }
kfree(ptr);
return NULL; return NULL;
} }
......
...@@ -143,6 +143,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, ...@@ -143,6 +143,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
goto out; goto out;
} }
requested_dev_name = tomoyo_realpath_from_path(&path); requested_dev_name = tomoyo_realpath_from_path(&path);
path_put(&path);
if (!requested_dev_name) { if (!requested_dev_name) {
error = -ENOENT; error = -ENOENT;
goto out; goto out;
......
...@@ -390,7 +390,7 @@ bool tomoyo_correct_domain(const unsigned char *domainname) ...@@ -390,7 +390,7 @@ bool tomoyo_correct_domain(const unsigned char *domainname)
if (!cp) if (!cp)
break; break;
if (*domainname != '/' || if (*domainname != '/' ||
!tomoyo_correct_word2(domainname, cp - domainname - 1)) !tomoyo_correct_word2(domainname, cp - domainname))
goto out; goto out;
domainname = cp + 1; domainname = cp + 1;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册