aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/capability.c19
-rw-r--r--security/keys/compat.c3
-rw-r--r--security/keys/gc.c1
-rw-r--r--security/keys/internal.h1
-rw-r--r--security/keys/keyctl.c102
-rw-r--r--security/keys/process_keys.c49
-rw-r--r--security/security.c17
-rw-r--r--security/selinux/hooks.c28
-rw-r--r--security/smack/smack_lsm.c30
-rw-r--r--security/tomoyo/tomoyo.c17
10 files changed, 267 insertions, 0 deletions
diff --git a/security/capability.c b/security/capability.c
index 06400cf07757..93a2ffe65905 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -373,6 +373,11 @@ static int cap_task_create(unsigned long clone_flags)
373 return 0; 373 return 0;
374} 374}
375 375
376static int cap_cred_alloc_blank(struct cred *cred, gfp_t gfp)
377{
378 return 0;
379}
380
376static void cap_cred_free(struct cred *cred) 381static void cap_cred_free(struct cred *cred)
377{ 382{
378} 383}
@@ -386,6 +391,10 @@ static void cap_cred_commit(struct cred *new, const struct cred *old)
386{ 391{
387} 392}
388 393
394static void cap_cred_transfer(struct cred *new, const struct cred *old)
395{
396}
397
389static int cap_kernel_act_as(struct cred *new, u32 secid) 398static int cap_kernel_act_as(struct cred *new, u32 secid)
390{ 399{
391 return 0; 400 return 0;
@@ -836,6 +845,13 @@ static int cap_key_getsecurity(struct key *key, char **_buffer)
836 return 0; 845 return 0;
837} 846}
838 847
848static int cap_key_session_to_parent(const struct cred *cred,
849 const struct cred *parent_cred,
850 struct key *key)
851{
852 return 0;
853}
854
839#endif /* CONFIG_KEYS */ 855#endif /* CONFIG_KEYS */
840 856
841#ifdef CONFIG_AUDIT 857#ifdef CONFIG_AUDIT
@@ -961,9 +977,11 @@ void security_fixup_ops(struct security_operations *ops)
961 set_to_cap_if_null(ops, file_receive); 977 set_to_cap_if_null(ops, file_receive);
962 set_to_cap_if_null(ops, dentry_open); 978 set_to_cap_if_null(ops, dentry_open);
963 set_to_cap_if_null(ops, task_create); 979 set_to_cap_if_null(ops, task_create);
980 set_to_cap_if_null(ops, cred_alloc_blank);
964 set_to_cap_if_null(ops, cred_free); 981 set_to_cap_if_null(ops, cred_free);
965 set_to_cap_if_null(ops, cred_prepare); 982 set_to_cap_if_null(ops, cred_prepare);
966 set_to_cap_if_null(ops, cred_commit); 983 set_to_cap_if_null(ops, cred_commit);
984 set_to_cap_if_null(ops, cred_transfer);
967 set_to_cap_if_null(ops, kernel_act_as); 985 set_to_cap_if_null(ops, kernel_act_as);
968 set_to_cap_if_null(ops, kernel_create_files_as); 986 set_to_cap_if_null(ops, kernel_create_files_as);
969 set_to_cap_if_null(ops, kernel_module_request); 987 set_to_cap_if_null(ops, kernel_module_request);
@@ -1063,6 +1081,7 @@ void security_fixup_ops(struct security_operations *ops)
1063 set_to_cap_if_null(ops, key_free); 1081 set_to_cap_if_null(ops, key_free);
1064 set_to_cap_if_null(ops, key_permission); 1082 set_to_cap_if_null(ops, key_permission);
1065 set_to_cap_if_null(ops, key_getsecurity); 1083 set_to_cap_if_null(ops, key_getsecurity);
1084 set_to_cap_if_null(ops, key_session_to_parent);
1066#endif /* CONFIG_KEYS */ 1085#endif /* CONFIG_KEYS */
1067#ifdef CONFIG_AUDIT 1086#ifdef CONFIG_AUDIT
1068 set_to_cap_if_null(ops, audit_rule_init); 1087 set_to_cap_if_null(ops, audit_rule_init);
diff --git a/security/keys/compat.c b/security/keys/compat.c
index c766c68a63bc..792c0a611a6d 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -82,6 +82,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
82 case KEYCTL_GET_SECURITY: 82 case KEYCTL_GET_SECURITY:
83 return keyctl_get_security(arg2, compat_ptr(arg3), arg4); 83 return keyctl_get_security(arg2, compat_ptr(arg3), arg4);
84 84
85 case KEYCTL_SESSION_TO_PARENT:
86 return keyctl_session_to_parent();
87
85 default: 88 default:
86 return -EOPNOTSUPP; 89 return -EOPNOTSUPP;
87 } 90 }
diff --git a/security/keys/gc.c b/security/keys/gc.c
index 44adc325e15c..1e616aef55fd 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -65,6 +65,7 @@ static void key_gc_timer_func(unsigned long data)
65 * - return true if we altered the keyring 65 * - return true if we altered the keyring
66 */ 66 */
67static bool key_gc_keyring(struct key *keyring, time_t limit) 67static bool key_gc_keyring(struct key *keyring, time_t limit)
68 __releases(key_serial_lock)
68{ 69{
69 struct keyring_list *klist; 70 struct keyring_list *klist;
70 struct key *key; 71 struct key *key;
diff --git a/security/keys/internal.h b/security/keys/internal.h
index fb830514c337..24ba0307b7ad 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -201,6 +201,7 @@ extern long keyctl_set_timeout(key_serial_t, unsigned);
201extern long keyctl_assume_authority(key_serial_t); 201extern long keyctl_assume_authority(key_serial_t);
202extern long keyctl_get_security(key_serial_t keyid, char __user *buffer, 202extern long keyctl_get_security(key_serial_t keyid, char __user *buffer,
203 size_t buflen); 203 size_t buflen);
204extern long keyctl_session_to_parent(void);
204 205
205/* 206/*
206 * debugging key validation 207 * debugging key validation
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 736d7800f97f..74c968524592 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1228,6 +1228,105 @@ long keyctl_get_security(key_serial_t keyid,
1228 return ret; 1228 return ret;
1229} 1229}
1230 1230
1231/*
1232 * attempt to install the calling process's session keyring on the process's
1233 * parent process
1234 * - the keyring must exist and must grant us LINK permission
1235 * - implements keyctl(KEYCTL_SESSION_TO_PARENT)
1236 */
1237long keyctl_session_to_parent(void)
1238{
1239 struct task_struct *me, *parent;
1240 const struct cred *mycred, *pcred;
1241 struct cred *cred, *oldcred;
1242 key_ref_t keyring_r;
1243 int ret;
1244
1245 keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK);
1246 if (IS_ERR(keyring_r))
1247 return PTR_ERR(keyring_r);
1248
1249 /* our parent is going to need a new cred struct, a new tgcred struct
1250 * and new security data, so we allocate them here to prevent ENOMEM in
1251 * our parent */
1252 ret = -ENOMEM;
1253 cred = cred_alloc_blank();
1254 if (!cred)
1255 goto error_keyring;
1256
1257 cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r);
1258 keyring_r = NULL;
1259
1260 me = current;
1261 write_lock_irq(&tasklist_lock);
1262
1263 parent = me->real_parent;
1264 ret = -EPERM;
1265
1266 /* the parent mustn't be init and mustn't be a kernel thread */
1267 if (parent->pid <= 1 || !parent->mm)
1268 goto not_permitted;
1269
1270 /* the parent must be single threaded */
1271 if (atomic_read(&parent->signal->count) != 1)
1272 goto not_permitted;
1273
1274 /* the parent and the child must have different session keyrings or
1275 * there's no point */
1276 mycred = current_cred();
1277 pcred = __task_cred(parent);
1278 if (mycred == pcred ||
1279 mycred->tgcred->session_keyring == pcred->tgcred->session_keyring)
1280 goto already_same;
1281
1282 /* the parent must have the same effective ownership and mustn't be
1283 * SUID/SGID */
1284 if (pcred-> uid != mycred->euid ||
1285 pcred->euid != mycred->euid ||
1286 pcred->suid != mycred->euid ||
1287 pcred-> gid != mycred->egid ||
1288 pcred->egid != mycred->egid ||
1289 pcred->sgid != mycred->egid)
1290 goto not_permitted;
1291
1292 /* the keyrings must have the same UID */
1293 if (pcred ->tgcred->session_keyring->uid != mycred->euid ||
1294 mycred->tgcred->session_keyring->uid != mycred->euid)
1295 goto not_permitted;
1296
1297 /* the LSM must permit the replacement of the parent's keyring with the
1298 * keyring from this process */
1299 ret = security_key_session_to_parent(mycred, pcred,
1300 key_ref_to_ptr(keyring_r));
1301 if (ret < 0)
1302 goto not_permitted;
1303
1304 /* if there's an already pending keyring replacement, then we replace
1305 * that */
1306 oldcred = parent->replacement_session_keyring;
1307
1308 /* the replacement session keyring is applied just prior to userspace
1309 * restarting */
1310 parent->replacement_session_keyring = cred;
1311 cred = NULL;
1312 set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME);
1313
1314 write_unlock_irq(&tasklist_lock);
1315 if (oldcred)
1316 put_cred(oldcred);
1317 return 0;
1318
1319already_same:
1320 ret = 0;
1321not_permitted:
1322 put_cred(cred);
1323 return ret;
1324
1325error_keyring:
1326 key_ref_put(keyring_r);
1327 return ret;
1328}
1329
1231/*****************************************************************************/ 1330/*****************************************************************************/
1232/* 1331/*
1233 * the key control system call 1332 * the key control system call
@@ -1313,6 +1412,9 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
1313 (char __user *) arg3, 1412 (char __user *) arg3,
1314 (size_t) arg4); 1413 (size_t) arg4);
1315 1414
1415 case KEYCTL_SESSION_TO_PARENT:
1416 return keyctl_session_to_parent();
1417
1316 default: 1418 default:
1317 return -EOPNOTSUPP; 1419 return -EOPNOTSUPP;
1318 } 1420 }
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 4739cfbb41b7..5c23afb31ece 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -17,6 +17,7 @@
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/err.h> 18#include <linux/err.h>
19#include <linux/mutex.h> 19#include <linux/mutex.h>
20#include <linux/security.h>
20#include <linux/user_namespace.h> 21#include <linux/user_namespace.h>
21#include <asm/uaccess.h> 22#include <asm/uaccess.h>
22#include "internal.h" 23#include "internal.h"
@@ -768,3 +769,51 @@ error:
768 abort_creds(new); 769 abort_creds(new);
769 return ret; 770 return ret;
770} 771}
772
773/*
774 * Replace a process's session keyring when that process resumes userspace on
775 * behalf of one of its children
776 */
777void key_replace_session_keyring(void)
778{
779 const struct cred *old;
780 struct cred *new;
781
782 if (!current->replacement_session_keyring)
783 return;
784
785 write_lock_irq(&tasklist_lock);
786 new = current->replacement_session_keyring;
787 current->replacement_session_keyring = NULL;
788 write_unlock_irq(&tasklist_lock);
789
790 if (!new)
791 return;
792
793 old = current_cred();
794 new-> uid = old-> uid;
795 new-> euid = old-> euid;
796 new-> suid = old-> suid;
797 new->fsuid = old->fsuid;
798 new-> gid = old-> gid;
799 new-> egid = old-> egid;
800 new-> sgid = old-> sgid;
801 new->fsgid = old->fsgid;
802 new->user = get_uid(old->user);
803 new->group_info = get_group_info(old->group_info);
804
805 new->securebits = old->securebits;
806 new->cap_inheritable = old->cap_inheritable;
807 new->cap_permitted = old->cap_permitted;
808 new->cap_effective = old->cap_effective;
809 new->cap_bset = old->cap_bset;
810
811 new->jit_keyring = old->jit_keyring;
812 new->thread_keyring = key_get(old->thread_keyring);
813 new->tgcred->tgid = old->tgcred->tgid;
814 new->tgcred->process_keyring = key_get(old->tgcred->process_keyring);
815
816 security_transfer_creds(new, old);
817
818 commit_creds(new);
819}
diff --git a/security/security.c b/security/security.c
index f88eaf6b14cc..d8b727637f02 100644
--- a/security/security.c
+++ b/security/security.c
@@ -684,6 +684,11 @@ int security_task_create(unsigned long clone_flags)
684 return security_ops->task_create(clone_flags); 684 return security_ops->task_create(clone_flags);
685} 685}
686 686
687int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
688{
689 return security_ops->cred_alloc_blank(cred, gfp);
690}
691
687void security_cred_free(struct cred *cred) 692void security_cred_free(struct cred *cred)
688{ 693{
689 security_ops->cred_free(cred); 694 security_ops->cred_free(cred);
@@ -699,6 +704,11 @@ void security_commit_creds(struct cred *new, const struct cred *old)
699 security_ops->cred_commit(new, old); 704 security_ops->cred_commit(new, old);
700} 705}
701 706
707void security_transfer_creds(struct cred *new, const struct cred *old)
708{
709 security_ops->cred_transfer(new, old);
710}
711
702int security_kernel_act_as(struct cred *new, u32 secid) 712int security_kernel_act_as(struct cred *new, u32 secid)
703{ 713{
704 return security_ops->kernel_act_as(new, secid); 714 return security_ops->kernel_act_as(new, secid);
@@ -1241,6 +1251,13 @@ int security_key_getsecurity(struct key *key, char **_buffer)
1241 return security_ops->key_getsecurity(key, _buffer); 1251 return security_ops->key_getsecurity(key, _buffer);
1242} 1252}
1243 1253
1254int security_key_session_to_parent(const struct cred *cred,
1255 const struct cred *parent_cred,
1256 struct key *key)
1257{
1258 return security_ops->key_session_to_parent(cred, parent_cred, key);
1259}
1260
1244#endif /* CONFIG_KEYS */ 1261#endif /* CONFIG_KEYS */
1245 1262
1246#ifdef CONFIG_AUDIT 1263#ifdef CONFIG_AUDIT
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c3bb31ecc5aa..134a9c0d2004 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3233,6 +3233,21 @@ static int selinux_task_create(unsigned long clone_flags)
3233} 3233}
3234 3234
3235/* 3235/*
3236 * allocate the SELinux part of blank credentials
3237 */
3238static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3239{
3240 struct task_security_struct *tsec;
3241
3242 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3243 if (!tsec)
3244 return -ENOMEM;
3245
3246 cred->security = tsec;
3247 return 0;
3248}
3249
3250/*
3236 * detach and free the LSM part of a set of credentials 3251 * detach and free the LSM part of a set of credentials
3237 */ 3252 */
3238static void selinux_cred_free(struct cred *cred) 3253static void selinux_cred_free(struct cred *cred)
@@ -3264,6 +3279,17 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3264} 3279}
3265 3280
3266/* 3281/*
3282 * transfer the SELinux data to a blank set of creds
3283 */
3284static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3285{
3286 const struct task_security_struct *old_tsec = old->security;
3287 struct task_security_struct *tsec = new->security;
3288
3289 *tsec = *old_tsec;
3290}
3291
3292/*
3267 * set the security data for a kernel service 3293 * set the security data for a kernel service
3268 * - all the creation contexts are set to unlabelled 3294 * - all the creation contexts are set to unlabelled
3269 */ 3295 */
@@ -5469,8 +5495,10 @@ static struct security_operations selinux_ops = {
5469 .dentry_open = selinux_dentry_open, 5495 .dentry_open = selinux_dentry_open,
5470 5496
5471 .task_create = selinux_task_create, 5497 .task_create = selinux_task_create,
5498 .cred_alloc_blank = selinux_cred_alloc_blank,
5472 .cred_free = selinux_cred_free, 5499 .cred_free = selinux_cred_free,
5473 .cred_prepare = selinux_cred_prepare, 5500 .cred_prepare = selinux_cred_prepare,
5501 .cred_transfer = selinux_cred_transfer,
5474 .kernel_act_as = selinux_kernel_act_as, 5502 .kernel_act_as = selinux_kernel_act_as,
5475 .kernel_create_files_as = selinux_kernel_create_files_as, 5503 .kernel_create_files_as = selinux_kernel_create_files_as,
5476 .kernel_module_request = selinux_kernel_module_request, 5504 .kernel_module_request = selinux_kernel_module_request,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index c243a2b25832..969f5fee1906 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1080,6 +1080,22 @@ static int smack_file_receive(struct file *file)
1080 */ 1080 */
1081 1081
1082/** 1082/**
1083 * smack_cred_alloc_blank - "allocate" blank task-level security credentials
1084 * @new: the new credentials
1085 * @gfp: the atomicity of any memory allocations
1086 *
1087 * Prepare a blank set of credentials for modification. This must allocate all
1088 * the memory the LSM module might require such that cred_transfer() can
1089 * complete without error.
1090 */
1091static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
1092{
1093 cred->security = NULL;
1094 return 0;
1095}
1096
1097
1098/**
1083 * smack_cred_free - "free" task-level security credentials 1099 * smack_cred_free - "free" task-level security credentials
1084 * @cred: the credentials in question 1100 * @cred: the credentials in question
1085 * 1101 *
@@ -1117,6 +1133,18 @@ static void smack_cred_commit(struct cred *new, const struct cred *old)
1117} 1133}
1118 1134
1119/** 1135/**
1136 * smack_cred_transfer - Transfer the old credentials to the new credentials
1137 * @new: the new credentials
1138 * @old: the original credentials
1139 *
1140 * Fill in a set of blank credentials from another set of credentials.
1141 */
1142static void smack_cred_transfer(struct cred *new, const struct cred *old)
1143{
1144 new->security = old->security;
1145}
1146
1147/**
1120 * smack_kernel_act_as - Set the subjective context in a set of credentials 1148 * smack_kernel_act_as - Set the subjective context in a set of credentials
1121 * @new: points to the set of credentials to be modified. 1149 * @new: points to the set of credentials to be modified.
1122 * @secid: specifies the security ID to be set 1150 * @secid: specifies the security ID to be set
@@ -3073,9 +3101,11 @@ struct security_operations smack_ops = {
3073 .file_send_sigiotask = smack_file_send_sigiotask, 3101 .file_send_sigiotask = smack_file_send_sigiotask,
3074 .file_receive = smack_file_receive, 3102 .file_receive = smack_file_receive,
3075 3103
3104 .cred_alloc_blank = smack_cred_alloc_blank,
3076 .cred_free = smack_cred_free, 3105 .cred_free = smack_cred_free,
3077 .cred_prepare = smack_cred_prepare, 3106 .cred_prepare = smack_cred_prepare,
3078 .cred_commit = smack_cred_commit, 3107 .cred_commit = smack_cred_commit,
3108 .cred_transfer = smack_cred_transfer,
3079 .kernel_act_as = smack_kernel_act_as, 3109 .kernel_act_as = smack_kernel_act_as,
3080 .kernel_create_files_as = smack_kernel_create_files_as, 3110 .kernel_create_files_as = smack_kernel_create_files_as,
3081 .task_setpgid = smack_task_setpgid, 3111 .task_setpgid = smack_task_setpgid,
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 35a13e7915e4..9548a0984cc4 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -14,6 +14,12 @@
14#include "tomoyo.h" 14#include "tomoyo.h"
15#include "realpath.h" 15#include "realpath.h"
16 16
17static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp)
18{
19 new->security = NULL;
20 return 0;
21}
22
17static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, 23static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,
18 gfp_t gfp) 24 gfp_t gfp)
19{ 25{
@@ -25,6 +31,15 @@ static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,
25 return 0; 31 return 0;
26} 32}
27 33
34static void tomoyo_cred_transfer(struct cred *new, const struct cred *old)
35{
36 /*
37 * Since "struct tomoyo_domain_info *" is a sharable pointer,
38 * we don't need to duplicate.
39 */
40 new->security = old->security;
41}
42
28static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) 43static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
29{ 44{
30 int rc; 45 int rc;
@@ -262,7 +277,9 @@ static int tomoyo_dentry_open(struct file *f, const struct cred *cred)
262 */ 277 */
263static struct security_operations tomoyo_security_ops = { 278static struct security_operations tomoyo_security_ops = {
264 .name = "tomoyo", 279 .name = "tomoyo",
280 .cred_alloc_blank = tomoyo_cred_alloc_blank,
265 .cred_prepare = tomoyo_cred_prepare, 281 .cred_prepare = tomoyo_cred_prepare,
282 .cred_transfer = tomoyo_cred_transfer,
266 .bprm_set_creds = tomoyo_bprm_set_creds, 283 .bprm_set_creds = tomoyo_bprm_set_creds,
267 .bprm_check_security = tomoyo_bprm_check_security, 284 .bprm_check_security = tomoyo_bprm_check_security,
268#ifdef CONFIG_SYSCTL 285#ifdef CONFIG_SYSCTL