aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2009-09-02 04:14:21 -0400
committerJames Morris <jmorris@namei.org>2009-09-02 07:29:22 -0400
commitee18d64c1f632043a02e6f5ba5e045bb26a5465f (patch)
tree80b5a4d530ec7d5fd69799920f0db7b78aba6b9d /include
parentd0420c83f39f79afb82010c2d2cafd150eef651b (diff)
KEYS: Add a keyctl to install a process's session keyring on its parent [try #6]
Add a keyctl to install a process's session keyring onto its parent. This replaces the parent's session keyring. Because the COW credential code does not permit one process to change another process's credentials directly, the change is deferred until userspace next starts executing again. Normally this will be after a wait*() syscall. To support this, three new security hooks have been provided: cred_alloc_blank() to allocate unset security creds, cred_transfer() to fill in the blank security creds and key_session_to_parent() - which asks the LSM if the process may replace its parent's session keyring. The replacement may only happen if the process has the same ownership details as its parent, and the process has LINK permission on the session keyring, and the session keyring is owned by the process, and the LSM permits it. Note that this requires alteration to each architecture's notify_resume path. This has been done for all arches barring blackfin, m68k* and xtensa, all of which need assembly alteration to support TIF_NOTIFY_RESUME. This allows the replacement to be performed at the point the parent process resumes userspace execution. This allows the userspace AFS pioctl emulation to fully emulate newpag() and the VIOCSETTOK and VIOCSETTOK2 pioctls, all of which require the ability to alter the parent process's PAG membership. However, since kAFS doesn't use PAGs per se, but rather dumps the keys into the session keyring, the session keyring of the parent must be replaced if, for example, VIOCSETTOK is passed the newpag flag. This can be tested with the following program: #include <stdio.h> #include <stdlib.h> #include <keyutils.h> #define KEYCTL_SESSION_TO_PARENT 18 #define OSERROR(X, S) do { if ((long)(X) == -1) { perror(S); exit(1); } } while(0) int main(int argc, char **argv) { key_serial_t keyring, key; long ret; keyring = keyctl_join_session_keyring(argv[1]); OSERROR(keyring, "keyctl_join_session_keyring"); key = add_key("user", "a", "b", 1, keyring); OSERROR(key, "add_key"); ret = keyctl(KEYCTL_SESSION_TO_PARENT); OSERROR(ret, "KEYCTL_SESSION_TO_PARENT"); return 0; } Compiled and linked with -lkeyutils, you should see something like: [dhowells@andromeda ~]$ keyctl show Session Keyring -3 --alswrv 4043 4043 keyring: _ses 355907932 --alswrv 4043 -1 \_ keyring: _uid.4043 [dhowells@andromeda ~]$ /tmp/newpag [dhowells@andromeda ~]$ keyctl show Session Keyring -3 --alswrv 4043 4043 keyring: _ses 1055658746 --alswrv 4043 4043 \_ user: a [dhowells@andromeda ~]$ /tmp/newpag hello [dhowells@andromeda ~]$ keyctl show Session Keyring -3 --alswrv 4043 4043 keyring: hello 340417692 --alswrv 4043 4043 \_ user: a Where the test program creates a new session keyring, sticks a user key named 'a' into it and then installs it on its parent. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'include')
-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
5 files changed, 44 insertions, 0 deletions
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