Merge branch 'next' into for-linus

This commit is contained in:
James Morris 2011-05-24 22:55:24 +10:00
commit 434d42cfd0
25 changed files with 205 additions and 64 deletions

View file

@ -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)
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))

View file

@ -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;
#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))

View file

@ -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,

View file

@ -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)))

View file

@ -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)
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);

View file

@ -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;

View file

@ -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,

View file

@ -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;
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);
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)
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 @@ unlock:
} }
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");

View file

@ -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[] = {
.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,

View file

@ -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);
}
} }
/* /*

View file

@ -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

View file

@ -529,15 +529,10 @@ skip:
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;
/* /*

View file

@ -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,

View file

@ -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);

View file

@ -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,
* @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,
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,
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 @@ descend:
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 @@ descend:
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,
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);

View file

@ -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);

View file

@ -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,
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,
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,
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,
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,
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;

View file

@ -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);

View file

@ -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);
} }
/* /*

View file

@ -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);

View file

@ -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)
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;
} }

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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;

View file

@ -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;
} }