aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/keys.txt20
-rw-r--r--arch/alpha/kernel/signal.c2
-rw-r--r--arch/arm/kernel/signal.c2
-rw-r--r--arch/avr32/kernel/signal.c2
-rw-r--r--arch/cris/kernel/ptrace.c2
-rw-r--r--arch/frv/kernel/signal.c2
-rw-r--r--arch/h8300/kernel/signal.c2
-rw-r--r--arch/ia64/kernel/process.c2
-rw-r--r--arch/m32r/kernel/signal.c2
-rw-r--r--arch/mips/kernel/signal.c2
-rw-r--r--arch/mn10300/kernel/signal.c2
-rw-r--r--arch/parisc/kernel/signal.c2
-rw-r--r--arch/s390/kernel/signal.c2
-rw-r--r--arch/sh/kernel/signal_32.c2
-rw-r--r--arch/sh/kernel/signal_64.c2
-rw-r--r--arch/sparc/kernel/signal_32.c2
-rw-r--r--arch/sparc/kernel/signal_64.c3
-rw-r--r--arch/x86/kernel/signal.c2
-rw-r--r--include/linux/cred.h1
-rw-r--r--include/linux/key.h3
-rw-r--r--include/linux/keyctl.h1
-rw-r--r--include/linux/sched.h1
-rw-r--r--include/linux/security.h38
-rw-r--r--kernel/cred.c43
-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
34 files changed, 409 insertions, 0 deletions
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 203487e9b1d8..e4dbbdb1bd96 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -757,6 +757,26 @@ The keyctl syscall functions are:
757 successful. 757 successful.
758 758
759 759
760 (*) Install the calling process's session keyring on its parent.
761
762 long keyctl(KEYCTL_SESSION_TO_PARENT);
763
764 This functions attempts to install the calling process's session keyring
765 on to the calling process's parent, replacing the parent's current session
766 keyring.
767
768 The calling process must have the same ownership as its parent, the
769 keyring must have the same ownership as the calling process, the calling
770 process must have LINK permission on the keyring and the active LSM module
771 mustn't deny permission, otherwise error EPERM will be returned.
772
773 Error ENOMEM will be returned if there was insufficient memory to complete
774 the operation, otherwise 0 will be returned to indicate success.
775
776 The keyring will be replaced next time the parent process leaves the
777 kernel and resumes executing userspace.
778
779
760=============== 780===============
761KERNEL SERVICES 781KERNEL SERVICES
762=============== 782===============
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 04e17c1f0f1b..d91aaa747050 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -687,5 +687,7 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
687 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 687 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
688 clear_thread_flag(TIF_NOTIFY_RESUME); 688 clear_thread_flag(TIF_NOTIFY_RESUME);
689 tracehook_notify_resume(regs); 689 tracehook_notify_resume(regs);
690 if (current->replacement_session_keyring)
691 key_replace_session_keyring();
690 } 692 }
691} 693}
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 13dec276927a..ea4ad3a43c88 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -711,5 +711,7 @@ do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
711 if (thread_flags & _TIF_NOTIFY_RESUME) { 711 if (thread_flags & _TIF_NOTIFY_RESUME) {
712 clear_thread_flag(TIF_NOTIFY_RESUME); 712 clear_thread_flag(TIF_NOTIFY_RESUME);
713 tracehook_notify_resume(regs); 713 tracehook_notify_resume(regs);
714 if (current->replacement_session_keyring)
715 key_replace_session_keyring();
714 } 716 }
715} 717}
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
index 62d242e2d033..de9f7fe2aefa 100644
--- a/arch/avr32/kernel/signal.c
+++ b/arch/avr32/kernel/signal.c
@@ -326,5 +326,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
326 if (ti->flags & _TIF_NOTIFY_RESUME) { 326 if (ti->flags & _TIF_NOTIFY_RESUME) {
327 clear_thread_flag(TIF_NOTIFY_RESUME); 327 clear_thread_flag(TIF_NOTIFY_RESUME);
328 tracehook_notify_resume(regs); 328 tracehook_notify_resume(regs);
329 if (current->replacement_session_keyring)
330 key_replace_session_keyring();
329 } 331 }
330} 332}
diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c
index 4f06d7fb43dd..32e9d5ee895b 100644
--- a/arch/cris/kernel/ptrace.c
+++ b/arch/cris/kernel/ptrace.c
@@ -40,5 +40,7 @@ void do_notify_resume(int canrestart, struct pt_regs *regs,
40 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 40 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
41 clear_thread_flag(TIF_NOTIFY_RESUME); 41 clear_thread_flag(TIF_NOTIFY_RESUME);
42 tracehook_notify_resume(regs); 42 tracehook_notify_resume(regs);
43 if (current->replacement_session_keyring)
44 key_replace_session_keyring();
43 } 45 }
44} 46}
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index 4a7a62c6e783..6b0a2b6fed6a 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -572,6 +572,8 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags)
572 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 572 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
573 clear_thread_flag(TIF_NOTIFY_RESUME); 573 clear_thread_flag(TIF_NOTIFY_RESUME);
574 tracehook_notify_resume(__frame); 574 tracehook_notify_resume(__frame);
575 if (current->replacement_session_keyring)
576 key_replace_session_keyring();
575 } 577 }
576 578
577} /* end do_notify_resume() */ 579} /* end do_notify_resume() */
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index 56b3ab7dbbb0..abac3ee8c52a 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -556,5 +556,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
556 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 556 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
557 clear_thread_flag(TIF_NOTIFY_RESUME); 557 clear_thread_flag(TIF_NOTIFY_RESUME);
558 tracehook_notify_resume(regs); 558 tracehook_notify_resume(regs);
559 if (current->replacement_session_keyring)
560 key_replace_session_keyring();
559 } 561 }
560} 562}
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 5d7c0e5b9e76..89969e950045 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -192,6 +192,8 @@ do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall)
192 if (test_thread_flag(TIF_NOTIFY_RESUME)) { 192 if (test_thread_flag(TIF_NOTIFY_RESUME)) {
193 clear_thread_flag(TIF_NOTIFY_RESUME); 193 clear_thread_flag(TIF_NOTIFY_RESUME);
194 tracehook_notify_resume(&scr->pt); 194 tracehook_notify_resume(&scr->pt);
195 if (current->replacement_session_keyring)
196 key_replace_session_keyring();
195 } 197 }
196 198
197 /* copy user rbs to kernel rbs */ 199 /* copy user rbs to kernel rbs */
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index 3220258be188..f80bac17c65c 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -411,6 +411,8 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
411 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 411 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
412 clear_thread_flag(TIF_NOTIFY_RESUME); 412 clear_thread_flag(TIF_NOTIFY_RESUME);
413 tracehook_notify_resume(regs); 413 tracehook_notify_resume(regs);
414 if (current->replacement_session_keyring)
415 key_replace_session_keyring();
414 } 416 }
415 417
416 clear_thread_flag(TIF_IRET); 418 clear_thread_flag(TIF_IRET);
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index a3d1015471de..c2acf31874a4 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -704,5 +704,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
704 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 704 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
705 clear_thread_flag(TIF_NOTIFY_RESUME); 705 clear_thread_flag(TIF_NOTIFY_RESUME);
706 tracehook_notify_resume(regs); 706 tracehook_notify_resume(regs);
707 if (current->replacement_session_keyring)
708 key_replace_session_keyring();
707 } 709 }
708} 710}
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c
index feb2f2e810db..a21f43bc68e2 100644
--- a/arch/mn10300/kernel/signal.c
+++ b/arch/mn10300/kernel/signal.c
@@ -568,5 +568,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
568 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 568 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
569 clear_thread_flag(TIF_NOTIFY_RESUME); 569 clear_thread_flag(TIF_NOTIFY_RESUME);
570 tracehook_notify_resume(__frame); 570 tracehook_notify_resume(__frame);
571 if (current->replacement_session_keyring)
572 key_replace_session_keyring();
571 } 573 }
572} 574}
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index b3bfc4326703..5ca1c02b805a 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -649,5 +649,7 @@ void do_notify_resume(struct pt_regs *regs, long in_syscall)
649 if (test_thread_flag(TIF_NOTIFY_RESUME)) { 649 if (test_thread_flag(TIF_NOTIFY_RESUME)) {
650 clear_thread_flag(TIF_NOTIFY_RESUME); 650 clear_thread_flag(TIF_NOTIFY_RESUME);
651 tracehook_notify_resume(regs); 651 tracehook_notify_resume(regs);
652 if (current->replacement_session_keyring)
653 key_replace_session_keyring();
652 } 654 }
653} 655}
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 062bd64e65fa..6b4fef877f9d 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -536,4 +536,6 @@ void do_notify_resume(struct pt_regs *regs)
536{ 536{
537 clear_thread_flag(TIF_NOTIFY_RESUME); 537 clear_thread_flag(TIF_NOTIFY_RESUME);
538 tracehook_notify_resume(regs); 538 tracehook_notify_resume(regs);
539 if (current->replacement_session_keyring)
540 key_replace_session_keyring();
539} 541}
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index b5afbec1db59..04a21883f327 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -640,5 +640,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,
640 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 640 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
641 clear_thread_flag(TIF_NOTIFY_RESUME); 641 clear_thread_flag(TIF_NOTIFY_RESUME);
642 tracehook_notify_resume(regs); 642 tracehook_notify_resume(regs);
643 if (current->replacement_session_keyring)
644 key_replace_session_keyring();
643 } 645 }
644} 646}
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c
index 0663a0ee6021..9e5c9b1d7e98 100644
--- a/arch/sh/kernel/signal_64.c
+++ b/arch/sh/kernel/signal_64.c
@@ -772,5 +772,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info
772 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 772 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
773 clear_thread_flag(TIF_NOTIFY_RESUME); 773 clear_thread_flag(TIF_NOTIFY_RESUME);
774 tracehook_notify_resume(regs); 774 tracehook_notify_resume(regs);
775 if (current->replacement_session_keyring)
776 key_replace_session_keyring();
775 } 777 }
776} 778}
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index 181d069a2d44..7ce1a1005b1d 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -590,6 +590,8 @@ void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0,
590 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 590 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
591 clear_thread_flag(TIF_NOTIFY_RESUME); 591 clear_thread_flag(TIF_NOTIFY_RESUME);
592 tracehook_notify_resume(regs); 592 tracehook_notify_resume(regs);
593 if (current->replacement_session_keyring)
594 key_replace_session_keyring();
593 } 595 }
594} 596}
595 597
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index ec82d76dc6f2..647afbda7ae1 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -613,5 +613,8 @@ void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long
613 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 613 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
614 clear_thread_flag(TIF_NOTIFY_RESUME); 614 clear_thread_flag(TIF_NOTIFY_RESUME);
615 tracehook_notify_resume(regs); 615 tracehook_notify_resume(regs);
616 if (current->replacement_session_keyring)
617 key_replace_session_keyring();
616 } 618 }
617} 619}
620
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 4c578751e94e..81e58238c4ce 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -869,6 +869,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
869 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 869 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
870 clear_thread_flag(TIF_NOTIFY_RESUME); 870 clear_thread_flag(TIF_NOTIFY_RESUME);
871 tracehook_notify_resume(regs); 871 tracehook_notify_resume(regs);
872 if (current->replacement_session_keyring)
873 key_replace_session_keyring();
872 } 874 }
873 875
874#ifdef CONFIG_X86_32 876#ifdef CONFIG_X86_32
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 85439abdbc80..24520a539c6f 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -152,6 +152,7 @@ struct cred {
152extern void __put_cred(struct cred *); 152extern void __put_cred(struct cred *);
153extern void exit_creds(struct task_struct *); 153extern void exit_creds(struct task_struct *);
154extern int copy_creds(struct task_struct *, unsigned long); 154extern int copy_creds(struct task_struct *, unsigned long);
155extern struct cred *cred_alloc_blank(void);
155extern struct cred *prepare_creds(void); 156extern struct cred *prepare_creds(void);
156extern struct cred *prepare_exec_creds(void); 157extern struct cred *prepare_exec_creds(void);
157extern struct cred *prepare_usermodehelper_creds(void); 158extern struct cred *prepare_usermodehelper_creds(void);
diff --git a/include/linux/key.h b/include/linux/key.h
index 33e0165de100..cd50dfa1d4c2 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -278,6 +278,8 @@ static inline key_serial_t key_serial(struct key *key)
278extern ctl_table key_sysctls[]; 278extern ctl_table key_sysctls[];
279#endif 279#endif
280 280
281extern void key_replace_session_keyring(void);
282
281/* 283/*
282 * the userspace interface 284 * the userspace interface
283 */ 285 */
@@ -300,6 +302,7 @@ extern void key_init(void);
300#define key_fsuid_changed(t) do { } while(0) 302#define key_fsuid_changed(t) do { } while(0)
301#define key_fsgid_changed(t) do { } while(0) 303#define key_fsgid_changed(t) do { } while(0)
302#define key_init() do { } while(0) 304#define key_init() do { } while(0)
305#define key_replace_session_keyring() do { } while(0)
303 306
304#endif /* CONFIG_KEYS */ 307#endif /* CONFIG_KEYS */
305#endif /* __KERNEL__ */ 308#endif /* __KERNEL__ */
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index c0688eb72093..bd383f1944fb 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -52,5 +52,6 @@
52#define KEYCTL_SET_TIMEOUT 15 /* set key timeout */ 52#define KEYCTL_SET_TIMEOUT 15 /* set key timeout */
53#define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */ 53#define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */
54#define KEYCTL_GET_SECURITY 17 /* get key security label */ 54#define KEYCTL_GET_SECURITY 17 /* get key security label */
55#define KEYCTL_SESSION_TO_PARENT 18 /* apply session keyring to parent process */
55 56
56#endif /* _LINUX_KEYCTL_H */ 57#endif /* _LINUX_KEYCTL_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 5c7ce13c1696..9304027673b0 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1292,6 +1292,7 @@ struct task_struct {
1292 struct mutex cred_guard_mutex; /* guard against foreign influences on 1292 struct mutex cred_guard_mutex; /* guard against foreign influences on
1293 * credential calculations 1293 * credential calculations
1294 * (notably. ptrace) */ 1294 * (notably. ptrace) */
1295 struct cred *replacement_session_keyring; /* for KEYCTL_SESSION_TO_PARENT */
1295 1296
1296 char comm[TASK_COMM_LEN]; /* executable name excluding path 1297 char comm[TASK_COMM_LEN]; /* executable name excluding path
1297 - access with [gs]et_task_comm (which lock 1298 - access with [gs]et_task_comm (which lock
diff --git a/include/linux/security.h b/include/linux/security.h
index 40ba39ea68ce..97de3fe3dd0d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -653,6 +653,11 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
653 * manual page for definitions of the @clone_flags. 653 * manual page for definitions of the @clone_flags.
654 * @clone_flags contains the flags indicating what should be shared. 654 * @clone_flags contains the flags indicating what should be shared.
655 * Return 0 if permission is granted. 655 * Return 0 if permission is granted.
656 * @cred_alloc_blank:
657 * @cred points to the credentials.
658 * @gfp indicates the atomicity of any memory allocations.
659 * Only allocate sufficient memory and attach to @cred such that
660 * cred_transfer() will not get ENOMEM.
656 * @cred_free: 661 * @cred_free:
657 * @cred points to the credentials. 662 * @cred points to the credentials.
658 * Deallocate and clear the cred->security field in a set of credentials. 663 * Deallocate and clear the cred->security field in a set of credentials.
@@ -665,6 +670,10 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
665 * @new points to the new credentials. 670 * @new points to the new credentials.
666 * @old points to the original credentials. 671 * @old points to the original credentials.
667 * Install a new set of credentials. 672 * Install a new set of credentials.
673 * @cred_transfer:
674 * @new points to the new credentials.
675 * @old points to the original credentials.
676 * Transfer data from original creds to new creds
668 * @kernel_act_as: 677 * @kernel_act_as:
669 * Set the credentials for a kernel service to act as (subjective context). 678 * Set the credentials for a kernel service to act as (subjective context).
670 * @new points to the credentials to be modified. 679 * @new points to the credentials to be modified.
@@ -1103,6 +1112,13 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
1103 * Return the length of the string (including terminating NUL) or -ve if 1112 * Return the length of the string (including terminating NUL) or -ve if
1104 * an error. 1113 * an error.
1105 * May also return 0 (and a NULL buffer pointer) if there is no label. 1114 * May also return 0 (and a NULL buffer pointer) if there is no label.
1115 * @key_session_to_parent:
1116 * Forcibly assign the session keyring from a process to its parent
1117 * process.
1118 * @cred: Pointer to process's credentials
1119 * @parent_cred: Pointer to parent process's credentials
1120 * @keyring: Proposed new session keyring
1121 * Return 0 if permission is granted, -ve error otherwise.
1106 * 1122 *
1107 * Security hooks affecting all System V IPC operations. 1123 * Security hooks affecting all System V IPC operations.
1108 * 1124 *
@@ -1498,10 +1514,12 @@ struct security_operations {
1498 int (*dentry_open) (struct file *file, const struct cred *cred); 1514 int (*dentry_open) (struct file *file, const struct cred *cred);
1499 1515
1500 int (*task_create) (unsigned long clone_flags); 1516 int (*task_create) (unsigned long clone_flags);
1517 int (*cred_alloc_blank) (struct cred *cred, gfp_t gfp);
1501 void (*cred_free) (struct cred *cred); 1518 void (*cred_free) (struct cred *cred);
1502 int (*cred_prepare)(struct cred *new, const struct cred *old, 1519 int (*cred_prepare)(struct cred *new, const struct cred *old,
1503 gfp_t gfp); 1520 gfp_t gfp);
1504 void (*cred_commit)(struct cred *new, const struct cred *old); 1521 void (*cred_commit)(struct cred *new, const struct cred *old);
1522 void (*cred_transfer)(struct cred *new, const struct cred *old);
1505 int (*kernel_act_as)(struct cred *new, u32 secid); 1523 int (*kernel_act_as)(struct cred *new, u32 secid);
1506 int (*kernel_create_files_as)(struct cred *new, struct inode *inode); 1524 int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
1507 int (*kernel_module_request)(void); 1525 int (*kernel_module_request)(void);
@@ -1639,6 +1657,9 @@ struct security_operations {
1639 const struct cred *cred, 1657 const struct cred *cred,
1640 key_perm_t perm); 1658 key_perm_t perm);
1641 int (*key_getsecurity)(struct key *key, char **_buffer); 1659 int (*key_getsecurity)(struct key *key, char **_buffer);
1660 int (*key_session_to_parent)(const struct cred *cred,
1661 const struct cred *parent_cred,
1662 struct key *key);
1642#endif /* CONFIG_KEYS */ 1663#endif /* CONFIG_KEYS */
1643 1664
1644#ifdef CONFIG_AUDIT 1665#ifdef CONFIG_AUDIT
@@ -1755,9 +1776,11 @@ int security_file_send_sigiotask(struct task_struct *tsk,
1755int security_file_receive(struct file *file); 1776int security_file_receive(struct file *file);
1756int security_dentry_open(struct file *file, const struct cred *cred); 1777int security_dentry_open(struct file *file, const struct cred *cred);
1757int security_task_create(unsigned long clone_flags); 1778int security_task_create(unsigned long clone_flags);
1779int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
1758void security_cred_free(struct cred *cred); 1780void security_cred_free(struct cred *cred);
1759int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp); 1781int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp);
1760void security_commit_creds(struct cred *new, const struct cred *old); 1782void security_commit_creds(struct cred *new, const struct cred *old);
1783void security_transfer_creds(struct cred *new, const struct cred *old);
1761int security_kernel_act_as(struct cred *new, u32 secid); 1784int security_kernel_act_as(struct cred *new, u32 secid);
1762int security_kernel_create_files_as(struct cred *new, struct inode *inode); 1785int security_kernel_create_files_as(struct cred *new, struct inode *inode);
1763int security_kernel_module_request(void); 1786int security_kernel_module_request(void);
@@ -2286,6 +2309,9 @@ static inline int security_task_create(unsigned long clone_flags)
2286 return 0; 2309 return 0;
2287} 2310}
2288 2311
2312static inline void security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
2313{ }
2314
2289static inline void security_cred_free(struct cred *cred) 2315static inline void security_cred_free(struct cred *cred)
2290{ } 2316{ }
2291 2317
@@ -2301,6 +2327,11 @@ static inline void security_commit_creds(struct cred *new,
2301{ 2327{
2302} 2328}
2303 2329
2330static inline void security_transfer_creds(struct cred *new,
2331 const struct cred *old)
2332{
2333}
2334
2304static inline int security_kernel_act_as(struct cred *cred, u32 secid) 2335static inline int security_kernel_act_as(struct cred *cred, u32 secid)
2305{ 2336{
2306 return 0; 2337 return 0;
@@ -2923,6 +2954,9 @@ void security_key_free(struct key *key);
2923int security_key_permission(key_ref_t key_ref, 2954int security_key_permission(key_ref_t key_ref,
2924 const struct cred *cred, key_perm_t perm); 2955 const struct cred *cred, key_perm_t perm);
2925int security_key_getsecurity(struct key *key, char **_buffer); 2956int security_key_getsecurity(struct key *key, char **_buffer);
2957int security_key_session_to_parent(const struct cred *cred,
2958 const struct cred *parent_cred,
2959 struct key *key);
2926 2960
2927#else 2961#else
2928 2962
@@ -2950,6 +2984,10 @@ static inline int security_key_getsecurity(struct key *key, char **_buffer)
2950 return 0; 2984 return 0;
2951} 2985}
2952 2986
2987static inline int security_key_session_to_parent(const struct cred *cred,
2988 const struct cred *parent_cred,
2989 struct key *key);
2990
2953#endif 2991#endif
2954#endif /* CONFIG_KEYS */ 2992#endif /* CONFIG_KEYS */
2955 2993
diff --git a/kernel/cred.c b/kernel/cred.c
index 24dd2f5104b1..006fcab009d5 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -199,6 +199,49 @@ void exit_creds(struct task_struct *tsk)
199 validate_creds(cred); 199 validate_creds(cred);
200 alter_cred_subscribers(cred, -1); 200 alter_cred_subscribers(cred, -1);
201 put_cred(cred); 201 put_cred(cred);
202
203 cred = (struct cred *) tsk->replacement_session_keyring;
204 if (cred) {
205 tsk->replacement_session_keyring = NULL;
206 validate_creds(cred);
207 put_cred(cred);
208 }
209}
210
211/*
212 * Allocate blank credentials, such that the credentials can be filled in at a
213 * later date without risk of ENOMEM.
214 */
215struct cred *cred_alloc_blank(void)
216{
217 struct cred *new;
218
219 new = kmem_cache_zalloc(cred_jar, GFP_KERNEL);
220 if (!new)
221 return NULL;
222
223#ifdef CONFIG_KEYS
224 new->tgcred = kzalloc(sizeof(*new->tgcred), GFP_KERNEL);
225 if (!new->tgcred) {
226 kfree(new);
227 return NULL;
228 }
229 atomic_set(&new->tgcred->usage, 1);
230#endif
231
232 atomic_set(&new->usage, 1);
233
234 if (security_cred_alloc_blank(new, GFP_KERNEL) < 0)
235 goto error;
236
237#ifdef CONFIG_DEBUG_CREDENTIALS
238 new->magic = CRED_MAGIC;
239#endif
240 return new;
241
242error:
243 abort_creds(new);
244 return NULL;
202} 245}
203 246
204/** 247/**
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