cred: #include init.h in cred.h
Subsystems (5)
PATCH 1/10 cred: #include init.h in cred.h
cred.h can't be included as first header because it uses __init and doesn't include init.h which is enough to break compilation on at least ia64.
--- include/linux/cred.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
include/linux/cred.h +1 -0
@@ -13,6 +13,7 @@#define _LINUX_CRED_H#include <linux/capability.h> +#include <linux/init.h> #include <linux/key.h> #include <asm/atomic.h>
Signature · 1 line
1.6.1
A message that is not in the archive (sent off-list or not yet received): 20090610014412.GA5628-r/[email protected]
PATCH 2/10 groups: move code to kernel/groups.c
Move supplementary groups implementation to kernel/groups.c . kernel/sys.c already accumulated quite a few random stuff.
Do strictly copy/paste + add required headers to compile. Compile-tested on many configs and archs.
--- kernel/Makefile | 1 + kernel/groups.c | 288 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/sys.c | 283 ------------------------------------------------------ 3 files changed, 289 insertions(+), 283 deletions(-) create mode 100644 kernel/groups.c
kernel/Makefile +1 -0
@@ -11,6 +11,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \ async.o +obj-y += groups.o ifdef CONFIG_FUNCTION_TRACER # Do not trace debug files and internal ftrace files
kernel/groups.c new file +288 -0
288 lines not on this page · raw message
kernel/sys.c +0 -283
289 lines not on this page · raw message
Signature · 1 line
1.6.1
PATCH 3/10 cr: break out new_user_ns()
In reply to a message not in the archiveBreak out the core function which checks privilege and (if allowed) creates a new user namespace, with the passed-in creating user_struct. Note that a user_namespace, unlike other namespace pointers, is not stored in the nsproxy. Rather it is purely a property of user_structs.
This will let us keep the task restore code simpler.
--- include/linux/user_namespace.h | 8 ++++++ kernel/user_namespace.c | 53 ++++++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 16 deletions(-)
include/linux/user_namespace.h +8 -0
@@ -20,6 +20,8 @@ extern struct user_namespace init_user_ns;#ifdef CONFIG_USER_NS +struct user_namespace *new_user_ns (struct user_struct *creator, +struct user_struct **newroot);static inline struct user_namespace *get_user_ns (struct user_namespace *ns) {if (ns)
@@ -38,6 +40,12 @@ static inline void put_user_ns(struct user_namespace *ns)#else +static inline struct user_namespace *new_user_ns (struct user_struct *creator, +struct user_struct **newroot) +{ +return -EINVAL ; +} +static inline struct user_namespace *get_user_ns (struct user_namespace *ns) {return &init_user_ns;
kernel/user_namespace.c +37 -16
80 lines not on this page · raw message
Signature · 1 line
1.6.1
PATCH 4/10 cr: split core function out of some set*{u,g}id functions
In reply to a message not in the archiveWhen restarting tasks, we want to be able to change xuid and xgid in a struct cred, and do so with security checks. Break the core functionality of set{fs,res}{u,g}id into cred_setX which performs the access checks based on current_cred(), but performs the requested change on a passed-in cred.
This will allow us to securely construct struct creds based on a checkpoint image, constrained by the caller's permissions, and apply them to the caller at the end of sys_restart().
--- include/linux/cred.h | 8 +++ kernel/cred.c | 114 ++++++++++++++++++++++++++++++++++++++++++ kernel/sys.c | 134 ++++++++------------------------------------------ 3 files changed, 143 insertions(+), 113 deletions(-)
include/linux/cred.h +8 -0
@@ -21,6 +21,9 @@ struct user_struct;struct cred ;struct inode ; +/* defined in sys.c, used in cred_setresuid */ +extern int set_user (struct cred *new); +/* * COW Supplementary groups list */
@@ -344,4 +347,9 @@ do { \ *(_fsgid) = __cred->fsgid; \ } while(0) +int cred_setresuid(struct cred *new, uid_t ruid, uid_t euid, uid_t suid); +int cred_setresgid (struct cred *new,gid_t rgid,gid_t egid,gid_t sgid); +int cred_setfsuid (struct cred *new,uid_t uid,uid_t *old_fsuid); +int cred_setfsgid (struct cred *new,gid_t gid,gid_t *old_fsgid); +#endif /* _LINUX_CRED_H */
kernel/cred.c +114 -0
117 lines not on this page · raw message
kernel/sys.c +21 -113
210 lines not on this page · raw message
Signature · 1 line
1.6.1
A message that is not in the archive (sent off-list or not yet received): 20090610014456.GC5658-r/[email protected]
Re: [PATCH 04/10] cr: split core function out of some set*{u,g}id functions
Quoted 6 lines · Serge E. Hallyn
When restarting tasks, we want to be able to change xuid and xgid in a struct cred, and do so with security checks. Break the core functionality of set{fs,res}{u,g}id into
cred_setXwhich performs the access checks based oncurrent_cred(), but performs the requested change on a passed-in cred.
Please cc the lsm list when making changes to security.
Signature · 2 lines
James Morris <jmorris-gx6/[email protected]>
Re: [PATCH 04/10] cr: split core function out of some set*{u,g}id functions
Quoted 10 lines · James Morris
Quoted 6 lines · Serge E. Hallyn
When restarting tasks, we want to be able to change xuid and xgid in a struct cred, and do so with security checks. Break the core functionality of set{fs,res}{u,g}id into
cred_setXwhich performs the access checks based oncurrent_cred(), but performs the requested change on a passed-in cred.Please cc the lsm list when making changes to security.
Argh, they were cc:d on my last version, and I was sure I'd put them in the list of headers for this set.
FWIW, the thread can be seen here
https://lists.linux-foundation.org/pipermail/containers/2009-June/018509.html
thanks,
-serge
PATCH 5/10 cr: ipc: reset kern_ipc_perms
In reply to a message not in the archiveReset the checkpointed uid and gid info on ipc objects.
Right now, we return -EPERM if the user calling sys_restart() isn't allowed to create an object with the checkpointed uid. We may prefer to simply use the caller's uid in that case - but that could lead to subtle userspace bugs? Unsure, so going for the stricter behavior.
TODO: restore kern_ipc_perms->security.
--- ipc/checkpoint.c | 33 +++++++++++++++++++++++++++++++-- 1 files changed, 31 insertions(+), 2 deletions(-)
ipc/checkpoint.c +31 -2
@@ -119,6 +119,26 @@ int checkpoint_ipc_ns(struct ckpt_ctx *ctx, struct ipc_namespace *ipc_ns)* Restart */ +/* +* check whether current task may create ipc object with +* checkpointed uids and gids. +* Return 1 if ok, 0 if not. +*/ +static int validate_created_perms (struct ckpt_hdr_ipc_perms *h) +{ +const struct cred *cred =current_cred (); +uid_t uid = cred->uid, euid = cred->euid; + +/* actually I don't know - is CAP_IPC_OWNER the right one? */ +if (((h->uid != uid && h->uid == euid) || + (h->cuid != uid && h->cuid != euid) || + !in_group_p (h->cgid) || + !in_group_p (h->gid)) && + !capable (CAP_IPC_OWNER )) +return 0 ; +return 1 ; +} +int restore_load_ipc_perms (struct ckpt_hdr_ipc_perms *h,struct kern_ipc_perm *perm) {
@@ -139,14 +159,23 @@ int restore_load_ipc_perms(struct ckpt_hdr_ipc_perms *h, perm->id = h->id; perm->key = h->key; -#if 0 /* FIX: requires security checks */ + +if (!validate_created_perms (h)) +return -EPERM ; perm->uid = h->uid; perm->gid = h->gid; perm->cuid = h->cuid; perm->cgid = h->cgid; -#endif perm->mode = h->mode; perm->seq = h->seq; +/* +* Todo: restore perm->security. +* At the moment it gets set by security_x_alloc() called through +* ipcget()->ipcget_public()->ops-.getnew (->nequeue for instance) +* We will want to ask the LSM to consider resetting the +* checkpointed ->security, based on current_security(), +* the checkpointed ->security, and the checkpoint file context. +*/ return 0 ; }
Signature · 1 line
1.6.1
PATCH 6/10 cr: capabilities: define checkpoint and restore fns
In reply to a message not in the archive[ Andrew: I am punting on dealing with the subsystem cooperation issues in this version, in favor of trying to get LSM issues straightened out ]
An application checkpoint image will store capability sets (and the bounding set) as __u64s. Define checkpoint and restart functions to translate between those and kernel_cap_t's.
Define a common function do_capset_tocred() which applies capability set changes to a passed-in struct cred.
The restore function uses do_capset_tocred() to apply the restored capabilities to the struct cred being crafted, subject to the current task's (task executing sys_restart()) permissions.
Changelog:
Jun 09: Can't choose securebits or drop bounding set if
file capabilities aren't compiled into the kernel. Also just store caps in __u32s (looks cleaner).
Jun 01: Made the checkpoint and restore functions and the
ckpt_hdr_capabilities struct more opaque to the rest of the c/r code, as suggested by Andrew Morgan, and using naming suggested by Oren.
Jun 01: Add commented BUILD_BUG_ON() to point out that the
current implementation depends on 64-bit capabilities. (Andrew Morgan and Alexey Dobriyan).
May 28: add helpers to c/r securebits
--- include/linux/capability.h | 6 ++ include/linux/checkpoint_hdr.h | 11 +++ kernel/capability.c | 162 +++++++++++++++++++++++++++++++++++++--- security/commoncap.c | 19 +---- 4 files changed, 170 insertions(+), 28 deletions(-)
include/linux/capability.h +6 -0
@@ -568,6 +568,12 @@ extern int capable(int cap);struct dentry ;extern int get_vfs_caps_from_disk (const struct dentry *dentry,struct cpu_vfs_cap_data *cpu_caps); +struct cred ; +int apply_securebits (unsigned securebits,struct cred *new); +struct ckpt_capabilities ; +int restore_capabilities (struct ckpt_capabilities *h,struct cred *new); +void checkpoint_capabilities (struct ckpt_capabilities *h,struct cred * cred); +#endif /* __KERNEL__ */ #endif /* !_LINUX_CAPABILITY_H */
include/linux/checkpoint_hdr.h +11 -0
@@ -56,6 +56,7 @@ enum {CKPT_HDR_NS ,CKPT_HDR_UTS_NS ,CKPT_HDR_IPC_NS , + CKPT_HDR_CAPABILITIES,/* 201-299: reserved for arch-dependent */
@@ -166,6 +167,16 @@ struct ckpt_hdr_task {__u32 task_comm_len; } __attribute__((aligned(8))); +/* Posix capabilities */ +struct ckpt_capabilities { +__u32 cap_i_0, cap_i_1;/* inheritable set */ +__u32 cap_p_0, cap_p_1;/* permitted set */ +__u32 cap_e_0, cap_e_1;/* effective set */ +__u32 cap_b_0, cap_b_1;/* bounding set */ +__u32 securebits; +__u32 padding; +} __attribute__((aligned (8 ))); +/* namespaces */ struct ckpt_hdr_task_ns {struct ckpt_hdr h;
kernel/capability.c +151 -11
191 lines not on this page · raw message
security/commoncap.c +2 -17
@@ -861,24 +861,9 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,* capability-based-privilege environment. */ case PR_SET_SECUREBITS : - error = -EPERM ; -if ((((new->securebits &SECURE_ALL_LOCKS ) >>1 ) - & (new->securebits ^ arg2))/*[1]*/ - || ((new->securebits &SECURE_ALL_LOCKS & ~arg2))/*[2]*/ - || (arg2 & ~(SECURE_ALL_LOCKS |SECURE_ALL_BITS ))/*[3]*/ - || (cap_capable (current,current_cred (),CAP_SETPCAP , -SECURITY_CAP_AUDIT ) !=0 )/*[4]*/ -/* -* [1] no changing of bits that are locked -* [2] no unlocking of locks -* [3] no setting of unsupported bits -* [4] doing anything requires privilege (go read about -* the "sendmail capabilities bug") -*/ - ) -/* cannot change a locked bit */ + error =apply_securebits (arg2, new); +if (error) goto error; - new->securebits = arg2; goto changed;case PR_GET_SECUREBITS :
Signature · 1 line
1.6.1
PATCH 7/10 cr: checkpoint and restore task credentials
In reply to a message not in the archiveThis patch adds the checkpointing and restart of credentials (uids, gids, and capabilities) to Oren's c/r patchset (on top of v14). It goes to great pains to re-use (and define when needed) common helpers, in order to make sure that as security code is modified, the cr code will be updated. Some of the helpers should still be moved (i.e. _creds() functions should be in kernel/cred.c).
When building the credentials for the restarted process, I
1. create a new struct cred as a copy of the running task's cred (using prepare_cred())
2. always authorize any changes to the new struct cred based on the permissions of current_cred() (not the current transient state of the new cred).
While this may mean that certain transient_cred1->transient_cred2 states are allowed which otherwise wouldn't be allowed, the fact remains that current_cred() is allowed to transition to transient_cred2.
The reconstructed creds are applied to the task at the very end of the sys_restart call. This ensures that any objects which need to be re-created (file, socket, etc) are re-created using the creds of the task calling sys_restart - preventing an unpriv user from creating a privileged object, and ensuring that a root task can restart a process which had started out privileged, created some privileged objects, then dropped its privilege.
With these patches, the root user can restart checkpoint images (created by either hallyn or root) of user hallyn's tasks, resulting in a program owned by hallyn.
Changelog:
Jun 01: Don't check ordering of groups in group_info, bc
set_groups() will sort it for us.
May 28: 1. Restore securebits
2. Address Alexey's comments: move prototypes out of sched.h, validate ngroups < NGROUPS_MAX, validate groups are sorted, and get rid of ckpt_hdr_cred->version.
3. remove bogus unused flag RESTORE_CREATE_USERNS
May 26: Move group, user, userns, creds c/r functions out
of checkpoint/process.c and into the appropriate files.
May 26: Define struct ckpt_hdr_task_creds and move task cred
objref c/r into {checkpoint_restore}_task_shared().
May 26: Take cred refs around checkpoint_write_creds() May 20: Remove the limit on number of groups in groupinfo
at checkpoint time
May 20: Remove the depth limit on empty user namespaces May 20: Better document checkpoint_user
May 18: fix more refcounting: if (userns 5, uid 0) had
no active tasks or child user_namespaces, then it shouldn't exist at restart or it, its namespace, and its whole chain of creators will be leaked.
May 14: fix some refcounting:
1. a new user_ns needs a ref to remain pinned
by its root user
2. current_user_ns needs an extra ref bc objhash drops two on restart
3. cred needs a ref for the real credentials bc commit_creds eats one ref.
May 13: folded in fix to userns refcounting.
--- checkpoint/objhash.c | 146 +++++++++++++++++++++++++++++++++---- checkpoint/process.c | 152 +++++++++++++++++++++++++++++++++++++- include/linux/checkpoint.h | 11 +++ include/linux/checkpoint_hdr.h | 60 +++++++++++++++ include/linux/checkpoint_types.h | 1 + include/linux/cred.h | 13 +++ include/linux/user_namespace.h | 6 ++ kernel/cred.c | 113 ++++++++++++++++++++++++++++ kernel/groups.c | 59 +++++++++++++++ kernel/user.c | 147 ++++++++++++++++++++++++++++++++++++ kernel/user_namespace.c | 86 +++++++++++++++++++++ 11 files changed, 778 insertions(+), 16 deletions(-)
checkpoint/objhash.c +132 -14
@@ -17,6 +17,7 @@#include <linux/fdtable.h> #include <linux/sched.h> #include <linux/ipc_namespace.h> +#include <linux/user_namespace.h> #include <linux/checkpoint.h> #include <linux/checkpoint_hdr.h>
@@ -181,6 +182,71 @@ static int obj_ipc_ns_users(void *ptr)return atomic_read (&((struct ipc_namespace *) ptr)->count); } +static int obj_cred_grab (void *ptr) +{ +get_cred ((struct cred *) ptr); +return 0 ; +} + +static void obj_cred_drop (void *ptr) +{ +put_cred ((struct cred *) ptr); +} + +static int obj_cred_users (void *ptr) +{ +return atomic_read (&((struct cred *) ptr)->usage); +} + +static int obj_user_grab (void *ptr) +{ +struct user_struct *u = ptr; + (void )get_uid (u); +return 0 ; +} + +static void obj_user_drop (void *ptr) +{ +free_uid ((struct user_struct *) ptr); +} + +static int obj_user_users (void *ptr) +{ +return atomic_read (&((struct user_struct *) ptr)->__count); +} + +static int obj_userns_grab (void *ptr) +{ +get_user_ns ((struct user_namespace *) ptr); +return 0 ; +} + +static void obj_userns_drop (void *ptr) +{ +put_user_ns ((struct user_namespace *) ptr); +} + +static int obj_user_ns_users (void *ptr) +{ +return atomic_read (&((struct user_namespace *) ptr)->kref.refcount); +} + +static int obj_groupinfo_grab (void *ptr) +{ +get_group_info ((struct group_info *) ptr); +return 0 ; +} + +static void obj_groupinfo_drop (void *ptr) +{ +put_group_info ((struct group_info *) ptr); +} + +static int obj_groupinfo_users (void *ptr) +{ +return atomic_read (&((struct group_info *) ptr)->usage); +} +static struct ckpt_obj_ops ckpt_obj_ops[] = {/* ignored object */ {
@@ -258,6 +324,46 @@ static struct ckpt_obj_ops ckpt_obj_ops[] = { .checkpoint = checkpoint_bad, .restore = restore_bad, }, +/* user_ns object */ + { + .obj_name = "USER_NS", + .obj_type = CKPT_OBJ_USER_NS, + .ref_drop = obj_userns_drop, + .ref_grab = obj_userns_grab, + .ref_users = obj_user_ns_users, + .checkpoint = checkpoint_userns, + .restore = restore_userns, + }, + /* struct cred */ + { + .obj_name = "CRED", + .obj_type = CKPT_OBJ_CRED, + .ref_drop = obj_cred_drop, + .ref_grab = obj_cred_grab, + .ref_users = obj_cred_users, + .checkpoint = checkpoint_cred, + .restore = restore_cred, + }, + /* user object */ + { + .obj_name = "USER", + .obj_type = CKPT_OBJ_USER, + .ref_drop = obj_user_drop, + .ref_grab = obj_user_grab, + .ref_users = obj_user_users, + .checkpoint = checkpoint_user, + .restore = restore_user, + }, + /* struct groupinfo */ + { + .obj_name = "GROUPINFO", + .obj_type = CKPT_OBJ_GROUPINFO, + .ref_drop = obj_groupinfo_drop, + .ref_grab = obj_groupinfo_grab, + .ref_users = obj_groupinfo_users, + .checkpoint = checkpoint_groupinfo, + .restore = restore_groupinfo, + }, };
@@ -313,6 +419,32 @@ int ckpt_obj_hash_alloc(struct ckpt_ctx *ctx)return 0 ; } +static struct ckpt_obj *obj_find_by_ptr (struct ckpt_ctx *ctx,void *ptr) +{ +struct hlist_head *h; +struct hlist_node *n; +struct ckpt_obj *obj; + + h = &ctx->obj_hash->head[hash_long ((unsigned long ) ptr, +CKPT_OBJ_HASH_NBITS )]; +hlist_for_each_entry (obj, n, h, hash) +if (obj->ptr == ptr) +return obj; +return NULL ; +} + +/* +* look up an obj and return objref if in hash, else +* return 0. Used during checkpoint. +*/ +int obj_lookup (struct ckpt_ctx *ctx,void *ptr) +{ +struct ckpt_obj *obj =obj_find_by_ptr (ctx, ptr); +if (obj) +return obj->objref; +return 0 ; +} +/** * ckpt_obj_new - add an object to the obj_hash * @ctx: checkpoint context
@@ -370,20 +502,6 @@ static struct ckpt_obj *obj_new(struct ckpt_ctx *ctx, void *ptr,* Checkpoint */ -static struct ckpt_obj *obj_find_by_ptr (struct ckpt_ctx *ctx,void *ptr) -{ -struct hlist_head *h; -struct hlist_node *n; -struct ckpt_obj *obj; - - h = &ctx->obj_hash->head[hash_long ((unsigned long ) ptr, -CKPT_OBJ_HASH_NBITS )]; -hlist_for_each_entry (obj, n, h, hash) -if (obj->ptr == ptr) -return obj; -return NULL ; -} -/** * obj_lookup_add - lookup object and add if not in objhash * @ctx: checkpoint context
checkpoint/process.c +150 -2
214 lines not on this page · raw message
include/linux/checkpoint.h +11 -0
@@ -97,6 +97,7 @@ extern void *ckpt_obj_fetch(struct ckpt_ctx *ctx, int objref, enum obj_type type);extern int ckpt_obj_lookup_add (struct ckpt_ctx *ctx,void *ptr,enum obj_type type,int *first); +extern int obj_lookup (struct ckpt_ctx *ctx,void *ptr);extern int ckpt_obj_insert (struct ckpt_ctx *ctx,void *ptr,int objref,enum obj_type type);
@@ -163,6 +164,16 @@ extern int checkpoint_file_common(struct ckpt_ctx *ctx, struct file *file,extern int restore_file_common (struct ckpt_ctx *ctx,struct file *file,struct ckpt_hdr_file *h); +/* credentials */ +int checkpoint_groupinfo (struct ckpt_ctx *ctx,void *ptr); +int checkpoint_userns (struct ckpt_ctx *ctx,void *ptr); +int checkpoint_user (struct ckpt_ctx *ctx,void *ptr); +int checkpoint_cred (struct ckpt_ctx *ctx,void *ptr); +void *restore_groupinfo (struct ckpt_ctx *ctx); +void *restore_userns (struct ckpt_ctx *ctx); +void *restore_user (struct ckpt_ctx *ctx); +void *restore_cred (struct ckpt_ctx *ctx); +/* memory */ extern void ckpt_pgarr_free (struct ckpt_ctx *ctx);
include/linux/checkpoint_hdr.h +60 -0
84 lines not on this page · raw message
include/linux/checkpoint_types.h +1 -0
@@ -65,6 +65,7 @@ struct ckpt_ctx {atomic_t tasks_count;/* sync of tasks: used to coordinate */ struct completion complete;/* container root and other tasks on */ wait_queue_head_t waitq;/* start, end, and restart ordering */ + struct cred *realcred, *ecred; /* tmp storage for cred at restart */ };#endif /* __KERNEL__ */
include/linux/cred.h +13 -0
@@ -77,6 +77,14 @@ extern int groups_search(const struct group_info *, gid_t);extern int in_group_p (gid_t );extern int in_egroup_p (gid_t ); +#ifdef CONFIG_CHECKPOINT +struct ckpt_ctx ; +int checkpoint_write_groupinfo (struct ckpt_ctx *,struct group_info *); +struct group_info *restore_read_groupinfo (struct ckpt_ctx *); +int checkpoint_write_user (struct ckpt_ctx *,struct user_struct *); +struct user_struct *restore_read_user (struct ckpt_ctx *); +#endif +/* * The common credentials for a thread group * - shared by CLONE_THREAD
@@ -352,4 +360,9 @@ int cred_setresgid(struct cred *new, gid_t rgid, gid_t egid, gid_t sgid);int cred_setfsuid (struct cred *new,uid_t uid,uid_t *old_fsuid);int cred_setfsgid (struct cred *new,gid_t gid,gid_t *old_fsgid); +#ifdef CONFIG_CHECKPOINT +int checkpoint_write_cred (struct ckpt_ctx *,const struct cred *); +struct cred *restore_read_cred (struct ckpt_ctx *); +#endif +#endif /* _LINUX_CRED_H */
include/linux/user_namespace.h +6 -0
@@ -62,4 +62,10 @@ static inline void put_user_ns(struct user_namespace *ns)#endif +#ifdef CONFIG_CHECKPOINT +struct ckpt_ctx ; +int checkpoint_write_userns (struct ckpt_ctx *,struct user_namespace *); +struct user_namespace *restore_read_userns (struct ckpt_ctx *); +#endif +#endif /* _LINUX_USER_H */
kernel/cred.c +113 -0
122 lines not on this page · raw message
kernel/groups.c +59 -0
68 lines not on this page · raw message
kernel/user.c +147 -0
156 lines not on this page · raw message
kernel/user_namespace.c +86 -0
95 lines not on this page · raw message
Signature · 1 line
1.6.1
PATCH 8/10 cr: restore file->f_cred
In reply to a message not in the archiveRestore a file's f_cred. This is set to the cred of the task doing the open, so often it will be the same as that of the restarted task.
--- checkpoint/files.c | 16 ++++++++++++++-- include/linux/checkpoint_hdr.h | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-)
checkpoint/files.c +14 -2
@@ -151,7 +151,11 @@ int checkpoint_file_common(struct ckpt_ctx *ctx, struct file *file, h->f_pos = file->f_pos; h->f_version = file->f_version; -/* FIX: need also file->uid, file->gid, file->f_owner, etc */ + h->f_credref =checkpoint_obj (ctx, file->f_cred,CKPT_OBJ_CRED ); +if (h->f_credref <0 ) +return h->f_credref; + +/* FIX: need also file->f_owner, etc */ return 0 ; }
@@ -440,8 +444,16 @@ int restore_file_common(struct ckpt_ctx *ctx, struct file *file, struct ckpt_hdr_file *h) {int ret; +struct cred *cred; + +/* FIX: need to restore owner etc */ -/* FIX: need to restore uid, gid, owner etc */ +/* restore the cred */ + cred =ckpt_obj_fetch (ctx, h->f_credref,CKPT_OBJ_CRED ); +if (IS_ERR (cred)) +return PTR_ERR (cred); +put_cred (file->f_cred); + file->f_cred =get_cred (cred);/* safe to set 1st arg (fd) to 0, as command is F_SETFL */ ret =vfs_fcntl (0 ,F_SETFL , h->f_flags &CKPT_SETFL_MASK , file);
include/linux/checkpoint_hdr.h +1 -1
@@ -306,7 +306,7 @@ struct ckpt_hdr_file {__u32 f_type;__u32 f_mode;__u32 f_flags; -__u32 _padding; +__s32 f_credref;__u64 f_pos;__u64 f_version; } __attribute__((aligned(8)));
Signature · 1 line
1.6.1
PATCH 9/10 cr: restore LSM credentials
In reply to a message not in the archiveCheckpoint and restore task and ipc struct ->security info. (files->f_security yet to be done).
LSM contexts (a string representation of obj->security) are checkpointed as shared objects before any object referencing it. The object's checkpoint header struct has a reference (h->sec_ref) to the shared object. A NULL ->security is indicated by h->sec_ref = -1.
At checkpoint time, for each obj->security to be checkpointed, the LSM will be asked (once) to convert it to a string, in memory which the checkpoint subsystem will kfree. At restart time, the LSM will first return some meaningful token given the checkpointed string. That token will be passed to per-object-type restore functions (task_restore_context(), shm_restore_security(), etc) where the LSM can determine based on the object type, the caller, and the token, whether to allow the object restore, and what value to actually assign to ->security. In smack, the token is the actual imported label. In SELinux, it is a temporary pointer to the sid which the checkpointed context referred to.
In smack, the checkpointed labels are used for both tasks and ipc objects so long as the task calling sys_restart() has CAP_MAC_ADMIN. Otherwise, if the checkpointed label is different from current_security(), -EPERM is returned.
The basics of SELinux support are there (enough to demonstrate working c/r with SELinux enforcing), but there will need to be new object permissions for restore, so the precise nature of those needs to be discussed. For instance, do we want to define process:restore and ipc_msg_msg:restore, in which case
allow root_t user_t:process restore
would mean that root_t may restart a task and label it user_t?
Since we are potentially skipping several allowed domain transitions (resulting in an illegal short-cut domain transition or type creation), I have a fear that the only sane way to proceed would be to have one all-powerful domain, checkpoint_restore_t, which can effectively transition to any domain it wants to by (ab)using the checkpoint image.
Or, perhaps we can define intermediate domains... So if we want user_t to be able to restart a server of type X_t, then we create a X_restore_t type, allow user_t to transition to it using a program which does sys_restart(), which in turn may transition to X_t?
Obviously this needs discussion.
Tomoyo has not been updated or tested. Given its path-based domain name model, I'm not sure what the tomoyo maintainers would prefer - that the restart program be reflected in the domain name, or that the original domain name be restored.
This is the first posting of this patch. There are testcases in git://git.sr71.net/~hallyn/cr_tests.git , in particular under (the slightly mis-named) cr_tests/userns/ directory. All pass fine with all LSMS (except Tomoyo, not tested).
--- checkpoint/objhash.c | 56 ++++++++++++ include/linux/checkpoint_hdr.h | 15 +++ include/linux/security.h | 105 +++++++++++++++++++++ ipc/checkpoint.c | 19 +++-- ipc/checkpoint_msg.c | 30 ++++++- ipc/checkpoint_sem.c | 12 +++- ipc/checkpoint_shm.c | 12 +++- ipc/util.h | 3 +- kernel/cred.c | 29 ++++++- security/capability.c | 47 ++++++++++ security/security.c | 39 ++++++++ security/selinux/hooks.c | 196 ++++++++++++++++++++++++++++++++++++++++ security/smack/smack_lsm.c | 135 +++++++++++++++++++++++++++ 13 files changed, 686 insertions(+), 12 deletions(-)
checkpoint/objhash.c +56 -0
@@ -20,6 +20,7 @@#include <linux/user_namespace.h> #include <linux/checkpoint.h> #include <linux/checkpoint_hdr.h> +#include <linux/security.h> struct ckpt_obj ;struct ckpt_obj_ops ;
@@ -247,6 +248,52 @@ static int obj_groupinfo_users(void *ptr)return atomic_read (&((struct group_info *) ptr)->usage); } +/* +* checkpoint_string - checkpoint a shared string +* @ctx: checkpoint context +* @str: string to checkpoint +* +* If ptr has already been checkpointed, return the objref +* Else write it to checkpoint image and return the objref +* On error, return <0. +*/ +#define MAX_STR_LEN 200 +static int checkpoint_security (struct ckpt_ctx *ctx,void *ptr) +{ +char *str; +int ret; +int len =0 ; + + str =security_context_to_str (ptr); +if (!str) +return 0 ; +if (IS_ERR (str)) +return PTR_ERR (str); + len =strlen (str) +1 ; +if (len >MAX_STR_LEN ) { +printk (KERN_NOTICE "%s: security context too long\n" , + __func__); +return -EINVAL ; + } + ret =ckpt_write_obj_type (ctx, str, len,CKPT_HDR_SEC ); +/* the LSM created a new string for us, now free it */ +kfree (str); +return ret; +} + +static void *restore_security (struct ckpt_ctx *ctx) +{ +struct ckpt_hdr_lsm *h; +void *security; + + h =ckpt_read_buf_type (ctx,MAX_STR_LEN ,CKPT_HDR_SEC ); +if (IS_ERR (h)) +return ERR_PTR (PTR_ERR (h)); + security =security_context_from_str (h->str); +ckpt_hdr_put (ctx, h); +return security; +} +static struct ckpt_obj_ops ckpt_obj_ops[] = {/* ignored object */ {
@@ -364,6 +411,15 @@ static struct ckpt_obj_ops ckpt_obj_ops[] = { .checkpoint = checkpoint_groupinfo, .restore = restore_groupinfo, }, +/* struct ckpt_sec */ + { + .obj_name = "SECURITY", + .obj_type = CKPT_OBJ_SEC, + .ref_drop = obj_no_drop, + .ref_grab = obj_no_grab, + .checkpoint = checkpoint_security, + .restore = restore_security, + }, };
include/linux/checkpoint_hdr.h +15 -0
@@ -45,6 +45,7 @@ enum {CKPT_HDR_BUFFER ,CKPT_HDR_STRING ,CKPT_HDR_OBJREF , +CKPT_HDR_SEC ,CKPT_HDR_TREE =101 , CKPT_HDR_TASK,
@@ -114,6 +115,7 @@ enum obj_type {CKPT_OBJ_CRED ,CKPT_OBJ_USER ,CKPT_OBJ_GROUPINFO , +CKPT_OBJ_SEC , CKPT_OBJ_MAX };
@@ -181,6 +183,13 @@ struct ckpt_hdr_task {__u32 task_comm_len; } __attribute__((aligned(8))); +/* LSM security contexts (shared) */ +struct ckpt_hdr_lsm { +struct ckpt_hdr h; +/* followed by `len' characters */ +char str[]; +} __attribute__((aligned (8 ))); +/* Posix capabilities */ struct ckpt_capabilities {__u32 cap_i_0, cap_i_1;/* inheritable set */
@@ -204,6 +213,8 @@ struct ckpt_hdr_cred {__s32 user_ref;__s32 groupinfo_ref;struct ckpt_capabilities cap_s; +__s32 sec_ref; +__u32 padding; } __attribute__((aligned(8)));struct ckpt_hdr_groupinfo {
@@ -418,6 +429,8 @@ struct ckpt_hdr_ipc_perms {__u32 mode;__u32 _padding;__u64 seq; +__s32 sec_ref; +__u32 padding; } __attribute__((aligned(8)));struct ckpt_hdr_ipc_shm {
@@ -451,6 +464,8 @@ struct ckpt_hdr_ipc_msg_msg {struct ckpt_hdr h;__s32 m_type;__u32 m_ts; +__s32 sec_ref; +__u32 padding; } __attribute__((aligned(8)));struct ckpt_hdr_ipc_sem {
include/linux/security.h +105 -0
217 lines not on this page · raw message
ipc/checkpoint.c +12 -7
@@ -27,7 +27,8 @@ static char *ipc_ind_to_str[] = { "sem", "msg", "shm" };* Checkpoint */ -int checkpoint_fill_ipc_perms (struct ckpt_hdr_ipc_perms *h, +int checkpoint_fill_ipc_perms (struct ckpt_ctx *ctx, +struct ckpt_hdr_ipc_perms *h,struct kern_ipc_perm *perm) {if (ipcperms (perm,S_IROTH ))
@@ -42,6 +43,13 @@ int checkpoint_fill_ipc_perms(struct ckpt_hdr_ipc_perms *h, h->mode = perm->mode &S_IRWXUGO ; h->seq = perm->seq; +if (perm->security) { + h->sec_ref =checkpoint_obj (ctx, perm->security,CKPT_OBJ_SEC ); +if (h->sec_ref <0 ) +return h->sec_ref; + }else + h->sec_ref =-1 ; +return 0 ; }
@@ -169,13 +177,10 @@ int restore_load_ipc_perms(struct ckpt_hdr_ipc_perms *h, perm->mode = h->mode; perm->seq = h->seq;/* -* Todo: restore perm->security. -* At the moment it gets set by security_x_alloc() called through -* ipcget()->ipcget_public()->ops-.getnew (->nequeue for instance) -* We will want to ask the LSM to consider resetting the -* checkpointed ->security, based on current_security(), -* the checkpointed ->security, and the checkpoint file context. +* The checkpointed ->security value will be restored +* (and verified) by our caller. */ + perm->security =NULL ;return 0 ; }
ipc/checkpoint_msg.c +29 -1
@@ -18,6 +18,7 @@#include <linux/syscalls.h> #include <linux/nsproxy.h> #include <linux/ipc_namespace.h> +#include <linux/security.h> #include "util.h"
@@ -36,7 +37,7 @@ static int fill_ipc_msg_hdr(struct ckpt_ctx *ctx,ipc_lock_by_ptr (&msq->q_perm); - ret =checkpoint_fill_ipc_perms (&h->perms, &msq->q_perm); + ret =checkpoint_fill_ipc_perms (ctx, &h->perms, &msq->q_perm);if (ret <0 ) goto unlock;
@@ -63,13 +64,20 @@ static int checkpoint_msg_contents(struct ckpt_ctx *ctx, struct msg_msg *msg)struct msg_msgseg *seg;int total, len;int ret; +int sec_ref =-1 ; +if (msg->security) { + sec_ref =checkpoint_obj (ctx, msg->security,CKPT_OBJ_SEC ); +if (sec_ref <0 ) +return sec_ref; + } h =ckpt_hdr_get_type (ctx,sizeof (*h),CKPT_HDR_IPC_MSG_MSG );if (!h)return -ENOMEM ; h->m_type = msg->m_type; h->m_ts = msg->m_ts; + h->sec_ref = sec_ref; ret =ckpt_write_obj (ctx, &h->h);ckpt_hdr_put (ctx, h);
@@ -175,10 +183,19 @@ static int load_ipc_msg_hdr(struct ckpt_ctx *ctx, struct msg_queue *msq) {int ret =0 ; +void *security =NULL ;; ret =restore_load_ipc_perms (&h->perms, &msq->q_perm);if (ret <0 )return ret; +if (h->perms.sec_ref !=-1 ) { + security =ckpt_obj_fetch (ctx, h->perms.sec_ref,CKPT_OBJ_SEC ); +if (IS_ERR (security)) +return PTR_ERR (security); + } + ret =security_msg_queue_restore (msq, security); +if (ret) +return ret;ckpt_debug ("msq: lspid %d lrpid %d qnum %lld qbytes %lld\n" , h->q_lspid, h->q_lrpid, h->q_qnum, h->q_qbytes);
@@ -200,6 +217,7 @@ static struct msg_msg *restore_msg_contents_one(struct ckpt_ctx *ctx, int *clen)struct ckpt_hdr_ipc_msg_msg *h;struct msg_msg *msg =NULL ;struct msg_msgseg *seg, **pseg; +void *security =NULL ;int total, len;int ret;
@@ -222,6 +240,16 @@ static struct msg_msg *restore_msg_contents_one(struct ckpt_ctx *ctx, int *clen) } msg->next =NULL ; pseg = &msg->next; +if (h->sec_ref !=-1 ) { + security =ckpt_obj_fetch (ctx, h->sec_ref,CKPT_OBJ_SEC ); +if (IS_ERR (security)) { + ret =PTR_ERR (security); + goto out; + } + } + ret =security_msg_msg_restore (msg, security); +if (ret) + goto out; ret =_ckpt_read_buffer (ctx, (msg +1 ), len);if (ret <0 )
ipc/checkpoint_sem.c +11 -1
@@ -18,6 +18,7 @@#include <linux/syscalls.h> #include <linux/nsproxy.h> #include <linux/ipc_namespace.h> +#include <linux/security.h> #include <linux/msg.h> /* needed for util.h that uses 'struct msg_msg' */ #include "util.h"
@@ -37,7 +38,7 @@ static int fill_ipc_sem_hdr(struct ckpt_ctx *ctx,ipc_lock_by_ptr (&sem->sem_perm); - ret =checkpoint_fill_ipc_perms (&h->perms, &sem->sem_perm); + ret =checkpoint_fill_ipc_perms (ctx, &h->perms, &sem->sem_perm);if (ret <0 ) goto unlock;
@@ -112,10 +113,19 @@ static int load_ipc_sem_hdr(struct ckpt_ctx *ctx, struct sem_array *sem) {int ret =0 ; +void *security =NULL ; ret =restore_load_ipc_perms (&h->perms, &sem->sem_perm);if (ret <0 )return ret; +if (h->perms.sec_ref !=-1 ) { + security =ckpt_obj_fetch (ctx, h->perms.sec_ref,CKPT_OBJ_SEC ); +if (IS_ERR (security)) +return PTR_ERR (security); + } + ret =security_sem_restore (sem, security); +if (ret) +return ret;ckpt_debug ("sem: nsems %u\n" , h->sem_nsems);
ipc/checkpoint_shm.c +11 -1
@@ -22,6 +22,7 @@#include <linux/nsproxy.h> #include <linux/ipc_namespace.h> #include <linux/deferqueue.h> +#include <linux/security.h> #include <linux/msg.h> /* needed for util.h that uses 'struct msg_msg' */ #include "util.h"
@@ -41,7 +42,7 @@ static int fill_ipc_shm_hdr(struct ckpt_ctx *ctx,ipc_lock_by_ptr (&shp->shm_perm); - ret =checkpoint_fill_ipc_perms (&h->perms, &shp->shm_perm); + ret =checkpoint_fill_ipc_perms (ctx, &h->perms, &shp->shm_perm);if (ret <0 ) goto unlock;
@@ -148,10 +149,19 @@ static int load_ipc_shm_hdr(struct ckpt_ctx *ctx, struct shmid_kernel *shp) {int ret; +void *security =NULL ; ret =restore_load_ipc_perms (&h->perms, &shp->shm_perm);if (ret <0 )return ret; +if (h->perms.sec_ref !=-1 ) { + security =ckpt_obj_fetch (ctx, h->perms.sec_ref,CKPT_OBJ_SEC ); +if (IS_ERR (security)) +return PTR_ERR (security); + } + ret =security_shm_restore (shp, security); +if (ret) +return ret;ckpt_debug ("shm: cprid %d lprid %d segsz %lld mlock %d\n" , h->shm_cprid, h->shm_lprid, h->shm_segsz, h->mlock_uid);
ipc/util.h +2 -1
@@ -192,7 +192,8 @@ extern void freeary(struct ipc_namespace *, struct kern_ipc_perm *);extern void do_shm_rmid (struct ipc_namespace *ns,struct kern_ipc_perm *ipcp);#ifdef CONFIG_CHECKPOINT -extern int checkpoint_fill_ipc_perms (struct ckpt_hdr_ipc_perms *h, +extern int checkpoint_fill_ipc_perms (struct ckpt_ctx *ctx, +struct ckpt_hdr_ipc_perms *h,struct kern_ipc_perm *perm);extern int restore_load_ipc_perms (struct ckpt_hdr_ipc_perms *h,struct kern_ipc_perm *perm);
kernel/cred.c +28 -1
@@ -709,8 +709,9 @@ int cred_setfsgid(struct cred *new, gid_t gid, gid_t *old_fsgid)int checkpoint_write_cred (struct ckpt_ctx *ctx,const struct cred *cred) {int ret; -int groupinfo_ref, user_ref; +int groupinfo_ref, user_ref, sec_ref =-1 ;struct ckpt_hdr_cred *h; +void *security =NULL ; groupinfo_ref =checkpoint_obj (ctx, cred->group_info,CKPT_OBJ_GROUPINFO );
@@ -719,6 +720,16 @@ int checkpoint_write_cred(struct ckpt_ctx *ctx, const struct cred *cred) user_ref =checkpoint_obj (ctx, cred->user,CKPT_OBJ_USER );if (user_ref <0 )return user_ref; +#ifdef CONFIG_SECURITY +/* should we checkpoint a 'lsm_na' field when !security ? */ + security = cred->security; +#endif + +if (security) { + sec_ref =checkpoint_obj (ctx, security,CKPT_OBJ_SEC ); +if (sec_ref <0 ) +return sec_ref; + } h =ckpt_hdr_get_type (ctx,sizeof (*h),CKPT_HDR_CRED );if (!h)
@@ -738,6 +749,7 @@ int checkpoint_write_cred(struct ckpt_ctx *ctx, const struct cred *cred) h->user_ref = user_ref; h->groupinfo_ref = groupinfo_ref; + h->sec_ref = sec_ref; ret =ckpt_write_obj (ctx, (struct ckpt_hdr *) h);ckpt_hdr_put (ctx, h);
@@ -751,6 +763,7 @@ struct cred *restore_read_cred(struct ckpt_ctx *ctx)struct ckpt_hdr_cred *h;struct user_struct *user;struct group_info *groupinfo; +void *security =NULL ;int ret = -EINVAL ;uid_t olduid;gid_t oldgid;
@@ -774,6 +787,20 @@ struct cred *restore_read_cred(struct ckpt_ctx *ctx) user =ckpt_obj_fetch (ctx, h->user_ref,CKPT_OBJ_USER );if (IS_ERR (user)) goto err_putcred; +if (h->sec_ref !=-1 ) + security =ckpt_obj_fetch (ctx, h->sec_ref,CKPT_OBJ_SEC ); +if (IS_ERR (security)) + goto err_putcred; + +#ifdef CONFIG_SECURITY +/* +* Ask LSM to reset original task->security if allowed +*/ + ret =security_task_restore_context (cred, security, + ctx->file->f_security); +if (ret) + goto err_putcred; +#endif /* * TODO: this check should go into the common helper in
security/capability.c +47 -0
100 lines not on this page · raw message
security/security.c +39 -0
@@ -827,6 +827,11 @@ int security_msg_msg_alloc(struct msg_msg *msg)return security_ops->msg_msg_alloc_security (msg); } +int security_msg_msg_restore (struct msg_msg *msg,void *stored) +{ +return security_ops->msg_msg_restore_security (msg, stored); +} +void security_msg_msg_free (struct msg_msg *msg) { security_ops->msg_msg_free_security (msg);
@@ -837,6 +842,11 @@ int security_msg_queue_alloc(struct msg_queue *msq)return security_ops->msg_queue_alloc_security (msq); } +int security_msg_queue_restore (struct msg_queue *msq,void *stored) +{ +return security_ops->msg_queue_restore_security (msq, stored); +} +void security_msg_queue_free (struct msg_queue *msq) { security_ops->msg_queue_free_security (msq);
@@ -869,6 +879,11 @@ int security_shm_alloc(struct shmid_kernel *shp)return security_ops->shm_alloc_security (shp); } +int security_shm_restore (struct shmid_kernel *shp,void *stored) +{ +return security_ops->shm_restore_security (shp, stored); +} +void security_shm_free (struct shmid_kernel *shp) { security_ops->shm_free_security (shp);
@@ -894,6 +909,11 @@ int security_sem_alloc(struct sem_array *sma)return security_ops->sem_alloc_security (sma); } +int security_sem_restore (struct sem_array *sma,void *stored) +{ +return security_ops->sem_restore_security (sma, stored); +} +void security_sem_free (struct sem_array *sma) { security_ops->sem_free_security (sma);
@@ -962,6 +982,25 @@ void security_release_secctx(char *secdata, u32 seclen) }EXPORT_SYMBOL (security_release_secctx); +char *security_context_to_str (void *security) +{ +return security_ops->context_to_str (security); +} +EXPORT_SYMBOL (security_context_to_str); + +void *security_context_from_str (char *str) +{ +return security_ops->context_from_str (str); +} +EXPORT_SYMBOL (security_context_from_str); + +int security_task_restore_context (struct cred *cred,void *stored, +void *f_security) +{ +return security_ops->task_restore_context (cred, stored, f_security); +} +EXPORT_SYMBOL (security_task_restore_context); +#ifdef CONFIG_SECURITY_NETWORK int security_unix_stream_connect(struct socket *sock, struct socket *other,
security/selinux/hooks.c +196 -0
253 lines not on this page · raw message
security/smack/smack_lsm.c +135 -0
192 lines not on this page · raw message
Signature · 7 lines
1.6.1 -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
A message that is not in the archive (sent off-list or not yet received): 20090610014637.GH5658-r/[email protected]
Re: [PATCH 09/10] cr: restore LSM credentials
Quoted 84 lines · Serge E. Hallyn
Checkpoint and restore task and ipc struct ->security info. (
files->f_securityyet to be done).LSM contexts (a string representation of
obj->security) are checkpointed as shared objects before any object referencing it. The object's checkpoint header struct has a reference (h->sec_ref) to the shared object. A NULL ->security is indicated byh->sec_ref= -1.At checkpoint time, for each
obj->securityto be checkpointed, the LSM will be asked (once) to convert it to a string, in memory which the checkpoint subsystem will kfree. At restart time, the LSM will first return some meaningful token given the checkpointed string. That token will be passed to per-object-type restore functions (task_restore_context(),shm_restore_security(), etc) where the LSM can determine based on the object type, the caller, and the token, whether to allow the object restore, and what value to actually assign to ->security. In smack, the token is the actual imported label. In SELinux, it is a temporary pointer to the sid which the checkpointed context referred to.In smack, the checkpointed labels are used for both tasks and ipc objects so long as the task calling
sys_restart()hasCAP_MAC_ADMIN. Otherwise, if the checkpointed label is different fromcurrent_security(),-EPERMis returned.The basics of SELinux support are there (enough to demonstrate working c/r with SELinux enforcing), but there will need to be new object permissions for restore, so the precise nature of those needs to be discussed. For instance, do we want to define process:restore and ipc_msg_msg:restore, in which case
allowroot_tuser_t:process restore
would mean thatroot_tmay restart a task and label ituser_t?Since we are potentially skipping several allowed domain transitions (resulting in an illegal short-cut domain transition or type creation), I have a fear that the only sane way to proceed would be to have one all-powerful domain,
checkpoint_restore_t, which can effectively transition to any domain it wants to by (ab)using the checkpoint image.Or, perhaps we can define intermediate domains... So if we want
user_tto be able to restart a server of typeX_t, then we create aX_restore_ttype, allowuser_tto transition to it using a program which doessys_restart(), which in turn may transition toX_t?Obviously this needs discussion.
Tomoyo has not been updated or tested. Given its path-based domain name model, I'm not sure what the tomoyo maintainers would prefer - that the restart program be reflected in the domain name, or that the original domain name be restored.
This is the first posting of this patch. There are testcases in
git://git.sr71.net/~hallyn/cr_tests.git, in particular under (the slightly mis-named) cr_tests/userns/ directory. All pass fine with all LSMS (except Tomoyo, not tested).Signed-off-by Serge E. Hallyn <serue-r/[email protected]>--- checkpoint/objhash.c | 56 ++++++++++++ include/linux/checkpoint_hdr.h | 15 +++ include/linux/security.h | 105 +++++++++++++++++++++ ipc/checkpoint.c | 19 +++-- ipc/checkpoint_msg.c | 30 ++++++- ipc/checkpoint_sem.c | 12 +++- ipc/checkpoint_shm.c | 12 +++- ipc/util.h | 3 +- kernel/cred.c | 29 ++++++- security/capability.c | 47 ++++++++++ security/security.c | 39 ++++++++ security/selinux/hooks.c | 196 ++++++++++++++++++++++++++++++++++++++++ security/smack/smack_lsm.c | 135 +++++++++++++++++++++++++++ 13 files changed, 686 insertions(+), 12 deletions(-)...
security/smack/smack_lsm.c +0
-0
security/smack/smack_lsm.c static int smack_msg_msg_alloc_security(struct msg_msg *msg) · line 1616
Quoted 9 lines
security/smack/smack_lsm.c +5
-0@@ -1608,6 +1608,32 @@ static int smack_msg_msg_alloc_security(struct msg_msg *msg) }/** +* smack_msg_msg_restore_security - Set the security blob for msg_msg +* @msg: the object +* @stored: the checkpointed label +* +* Returns 0
Comment ought to reflect the actual behavior.
security/smack/smack_lsm.c static int smack_msg_msg_alloc_security(struct msg_msg *msg)
Quoted 7 lines
security/smack/smack_lsm.c +6
-0+*/ +static int smack_msg_msg_restore_security (struct msg_msg *msg, +void *stored) +{ +struct kern_ipc_perm *isp = &sma->sem_perm; +char *str =smk_import (stored,0 );
To be really nit-picky, I'd prefer a variable name that indicates it's a Smack label rather than just any old character string. Perhaps
char *smack = smk_import(stored, 0);
security/smack/smack_lsm.c static int smack_msg_msg_alloc_security(struct msg_msg *msg)
Quoted 13 lines
security/smack/smack_lsm.c +12
-0+ +if (str ==NULL ) +return -EINVAL ; + + msg->security =current_security (); +if (current_security () != str) { +if (!capable (CAP_MAC_ADMIN )) +return -EPERM ; + msg->security = str; + } +return 0 ; +return 0 ;
Returning once is sufficient.
Quoted 7 lines
security/smack/smack_lsm.c +3
-0+} + +/** *
smack_msg_msg_free_security- Clear the security blob formsg_msg
* @msg: the object
*
security/smack/smack_lsm.c static int smack_shm_alloc_security(struct shmid_kernel *shp) · line 1678
Quoted 9 lines
security/smack/smack_lsm.c +5
-0@@ -1644,6 +1670,30 @@ static int smack_shm_alloc_security(struct shmid_kernel *shp) }/** +* smack_shm_restore_security - retore the security blob for shm +* @shp: the object +* @stored: the checkpointed label +* +* Returns 0
Previous comment comment applies here as well.
Quoted 23 lines
security/smack/smack_lsm.c +19
-0+*/ +static int smack_shm_restore_security (struct shmid_kernel *shp,void *stored) +{ +struct kern_ipc_perm *isp = &shp->shm_perm; +char *str =smk_import (stored,0 ); + +if (str ==NULL ) +return -EINVAL ; + + isp->security =current_security (); +if (current_security () != str) { +if (!capable (CAP_MAC_ADMIN )) +return -EPERM ; + isp->security = str; + } +return 0 ; +} + +/** * smack_shm_free_security - Clear the security blob for shm * @shp: the object *
security/smack/smack_lsm.c static int smack_sem_alloc_security(struct sem_array *sma) · line 1811
Quoted 9 lines
security/smack/smack_lsm.c +5
-0@@ -1753,6 +1803,31 @@ static int smack_sem_alloc_security(struct sem_array *sma) }/** +* smack_sem_restore_security - Set the security blob for sem +* @sma: the object +* @stored: the label stored in checkpoint image +* +* Returns 0
Or an error if the label is bad, as above.
Quoted 24 lines
security/smack/smack_lsm.c +20
-0+*/ +static int smack_sem_restore_security (struct sem_array *sma, +void *stored) +{ +struct kern_ipc_perm *isp = &sma->sem_perm; +char *str =smk_import (stored,0 ); + +if (str ==NULL ) +return -EINVAL ; + + isp->security =current_security (); +if (current_security () != str) { +if (!capable (CAP_MAC_ADMIN )) +return -EPERM ; + isp->security = str; + } +return 0 ; +} + +/** * smack_sem_free_security - Clear the security blob for sem * @sma: the object *
security/smack/smack_lsm.c static int smack_msg_queue_alloc_security(struct msg_queue *msq) · line 1940
Quoted 9 lines
security/smack/smack_lsm.c +5
-0@@ -1857,6 +1932,31 @@ static int smack_msg_queue_alloc_security(struct msg_queue *msq) }/** +* smack_msg_restore_security - Set the security blob for msg +* @msq: the object +* @stored: the stored label +* +* Returns 0
And again ...
Quoted 96 lines
security/smack/smack_lsm.c +20
-0+*/ +static int smack_msg_queue_restore_security (struct msg_queue *msq, +void *stored) +{ +struct kern_ipc_perm *kisp = &msq->q_perm; +char *str =smk_import (stored,0 ); + +if (str ==NULL ) +return -EINVAL ; + + kisp->security =current_security (); +if (current_security () != str) { +if (!capable (CAP_MAC_ADMIN )) +return -EPERM ; + kisp->security = str; + } +return 0 ; +} + +/** * smack_msg_free_security - Clear the security blob for msg * @msq: the object *
security/smack/smack_lsm.c +35
-0@@ -2823,6 +2923,33 @@ static void smack_release_secctx(char *secdata, u32 seclen) { } +/* checkpoint/restore hooks */ +static char *smack_context_to_str (void *security) +{ +return kstrdup ((char *)security,GFP_KERNEL ); +} + +static void *smack_context_from_str (char *str) +{ +char *newsmack =smk_import (str,0 ); + +if (newsmack ==NULL ) +return ERR_PTR (-EINVAL ); + +return newsmack; +} + +static int smack_task_restore_context (struct cred *cred,void *stored, +void *f_security) +{ +if (cred->security != stored) { +if (!capable (CAP_MAC_ADMIN )) +return -EPERM ; + cred->security = stored; + } +return 0 ; +} +struct security_operations smack_ops = { .name ="smack" ,@@ -2902,9 +3029,11 @@ struct security_operations smack_ops = { .ipc_getsecid = smack_ipc_getsecid, .msg_msg_alloc_security = smack_msg_msg_alloc_security, + .msg_msg_restore_security = smack_msg_msg_restore_security, .msg_msg_free_security = smack_msg_msg_free_security, .msg_queue_alloc_security = smack_msg_queue_alloc_security, + .msg_queue_restore_security = smack_msg_queue_restore_security, .msg_queue_free_security = smack_msg_queue_free_security, .msg_queue_associate = smack_msg_queue_associate, .msg_queue_msgctl = smack_msg_queue_msgctl,@@ -2912,12 +3041,14 @@ struct security_operations smack_ops = { .msg_queue_msgrcv = smack_msg_queue_msgrcv, .shm_alloc_security = smack_shm_alloc_security, + .shm_restore_security = smack_shm_restore_security, .shm_free_security = smack_shm_free_security, .shm_associate = smack_shm_associate, .shm_shmctl = smack_shm_shmctl, .shm_shmat = smack_shm_shmat, .sem_alloc_security = smack_sem_alloc_security, + .sem_restore_security = smack_sem_restore_security, .sem_free_security = smack_sem_free_security, .sem_associate = smack_sem_associate, .sem_semctl = smack_sem_semctl,@@ -2964,6 +3095,10 @@ struct security_operations smack_ops = { .secid_to_secctx = smack_secid_to_secctx, .secctx_to_secid = smack_secctx_to_secid, .release_secctx = smack_release_secctx, + + .context_to_str = smack_context_to_str, + .context_from_str = smack_context_from_str, + .task_restore_context = smack_task_restore_context, };
Re: [PATCH 09/10] cr: restore LSM credentials
In reply to a message not in the archiveQuoted 9 lines · Serge E. Hallyn
Checkpoint and restore task and ipc struct ->security info. (
files->f_securityyet to be done).LSM contexts (a string representation of
obj->security) are checkpointed as shared objects before any object referencing it. The object's checkpoint header struct has a reference (h->sec_ref) to the shared object. A NULL ->security is indicated byh->sec_ref= -1.
Quoted 11 lines
At checkpoint time, for each
obj->securityto be checkpointed, the LSM will be asked (once) to convert it to a string, in memory which the checkpoint subsystem will kfree. At restart time, the LSM will first return some meaningful token given the checkpointed string. That token will be passed to per-object-type restore functions (task_restore_context(),shm_restore_security(), etc) where the LSM can determine based on the object type, the caller, and the token, whether to allow the object restore, and what value to actually assign to ->security. In smack, the token is the actual imported label. In SELinux, it is a temporary pointer to the sid which the checkpointed context referred to.
Possibly I misunderstand, but it appears that you have a single security_context_to_str() hook that tries to take an arbitrary ->security pointer for any object type. I don't believe that is safe, as each object type may have its own security structure.
There are already LSM hooks to obtain secids for objects (task, ipc, inode, sock), and to convert between secid and secctx strings for use by the audit subsystem and networking subsystem. Why can't you just use those hooks for getting the secids and then converting them to secctx strings later?
Quoted 5 lines
In smack, the checkpointed labels are used for both tasks and ipc objects so long as the task calling
sys_restart()hasCAP_MAC_ADMIN. Otherwise, if the checkpointed label is different fromcurrent_security(),-EPERMis returned.
Quoted 7 lines
The basics of SELinux support are there (enough to demonstrate working c/r with SELinux enforcing), but there will need to be new object permissions for restore, so the precise nature of those needs to be discussed. For instance, do we want to define process:restore and ipc_msg_msg:restore, in which case
allowroot_tuser_t:process restore
would mean thatroot_tmay restart a task and label ituser_t?
I think so, yes.
Quoted 7 lines
Since we are potentially skipping several allowed domain transitions (resulting in an illegal short-cut domain transition or type creation), I have a fear that the only sane way to proceed would be to have one all-powerful domain,
checkpoint_restore_t, which can effectively transition to any domain it wants to by (ab)using the checkpoint image.
Quoted 5 lines
Or, perhaps we can define intermediate domains... So if we want
user_tto be able to restart a server of typeX_t, then we create aX_restore_ttype, allowuser_tto transition to it using a program which doessys_restart(), which in turn may transition toX_t?
Different domains will make sense for different use cases. As long as the mechanism doesn't prevent us from crafting more limited privilege restore domains in policy, it shouldn't be a problem.
Signature · 2 lines
Stephen Smalley National Security Agency
A message that is not in the archive (sent off-list or not yet received): 1244642042.20265.143.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]
Re: [PATCH 09/10] cr: restore LSM credentials
Quoted 10 lines · Stephen Smalley
Quoted 9 lines · Serge E. Hallyn
Checkpoint and restore task and ipc struct ->security info. (
files->f_securityyet to be done).LSM contexts (a string representation of
obj->security) are checkpointed as shared objects before any object referencing it. The object's checkpoint header struct has a reference (h->sec_ref) to the shared object. A NULL ->security is indicated byh->sec_ref= -1.
Quoted 11 lines
Quoted 11 lines
At checkpoint time, for each
obj->securityto be checkpointed, the LSM will be asked (once) to convert it to a string, in memory which the checkpoint subsystem will kfree. At restart time, the LSM will first return some meaningful token given the checkpointed string. That token will be passed to per-object-type restore functions (task_restore_context(),shm_restore_security(), etc) where the LSM can determine based on the object type, the caller, and the token, whether to allow the object restore, and what value to actually assign to ->security. In smack, the token is the actual imported label. In SELinux, it is a temporary pointer to the sid which the checkpointed context referred to.
Thanks for taking a look.
Quoted 2 lines
Possibly I misunderstand, but it appears that you have a single
security_context_to_str()hook that tries to take an arbitrary
Yikes, you're right. And I remember telling myself that wouldn't work - then apparently I ran into the next problem and forgot.
Quoted 2 lines
->security pointer for any object type. I don't believe that is safe, as each object type may have its own security structure.
Absolutely. Which begs the question why it was working for me :)
Quoted 5 lines
There are already LSM hooks to obtain secids for objects (task, ipc, inode, sock), and to convert between secid and secctx strings for use by the audit subsystem and networking subsystem. Why can't you just use those hooks for getting the secids and then converting them to secctx strings later?
I had taken a look at the *_secid() hooks, and think I misunderstood them. Using those makes sense; I'll make that change.
Quoted 13 lines
Quoted 5 lines
In smack, the checkpointed labels are used for both tasks and ipc objects so long as the task calling
sys_restart()hasCAP_MAC_ADMIN. Otherwise, if the checkpointed label is different fromcurrent_security(),-EPERMis returned.Quoted 7 lines
The basics of SELinux support are there (enough to demonstrate working c/r with SELinux enforcing), but there will need to be new object permissions for restore, so the precise nature of those needs to be discussed. For instance, do we want to define process:restore and ipc_msg_msg:restore, in which case
allowroot_tuser_t:process restore
would mean thatroot_tmay restart a task and label ituser_t?
Quoted 1 line
I think so, yes.
Ok, I'll define those in the next set.
thanks,
-serge
PATCH 10/10 cr: lsm: restore file->f_security
In reply to a message not in the archivefile->f_cred is the cred of the task which opened it. file->f_security can be separately set by the LSM. Checkpoint the file->f_security, and at restart ask the LSM, using security_file_restore, based on the current task's context and the checkpointed f_security, which f_security to apply (or whether to refuse the restart altogether).
For Smack, accept the checkpointed label if the restarting task has CAP_MAC_ADMIN.
For SELinux, I currently ignore the checkpointed label and call file_alloc_security(). Do we want to have 'restore' permission for class file?
--- checkpoint/files.c | 33 +++++++++++++++++++++++++++++++++ include/linux/checkpoint_hdr.h | 1 + include/linux/security.h | 13 +++++++++++++ security/capability.c | 6 ++++++ security/security.c | 5 +++++ security/selinux/hooks.c | 11 +++++++++++ security/smack/smack_lsm.c | 26 +++++++++++++++++++++++++- 7 files changed, 94 insertions(+), 1 deletions(-)
checkpoint/files.c +33 -0
@@ -19,6 +19,7 @@#include <linux/fsnotify.h> #include <linux/pipe_fs_i.h> #include <linux/syscalls.h> +#include <linux/security.h> #include <linux/checkpoint.h> #include <linux/checkpoint_hdr.h>
@@ -155,6 +156,14 @@ int checkpoint_file_common(struct ckpt_ctx *ctx, struct file *file,if (h->f_credref <0 )return h->f_credref; +#ifdef CONFIG_SECURITY +if (file->f_security) { + h->f_secref =checkpoint_obj (ctx, file->f_security,CKPT_OBJ_SEC ); +if (h->f_secref <0 ) +return h->f_secref; + }else + h->f_secref =-1 ; +#endif /* FIX: need also file->f_owner, etc */ return 0 ;
@@ -437,6 +446,26 @@ static int attach_file(struct file *file)return fd; } +#ifdef CONFIG_SECURITY +int restore_file_security (struct ckpt_ctx *ctx,struct file *file, +struct ckpt_hdr_file *h) +{ +void *security =NULL ; + +if (h->f_secref !=-1 ) + security =ckpt_obj_fetch (ctx, h->f_secref,CKPT_OBJ_SEC ); +if (IS_ERR (security)) +return PTR_ERR (security); +return security_file_restore (file, security); +} +#else +static inline int restore_file_security (struct ckpt_ctx *ctx, +struct file *file,struct ckpt_hdr_file *h) +{ +return 0 ; +} +#endif +#define CKPT_SETFL_MASK \ (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME)
@@ -455,6 +484,10 @@ int restore_file_common(struct ckpt_ctx *ctx, struct file *file,put_cred (file->f_cred); file->f_cred =get_cred (cred); + ret =restore_file_security (ctx, file, h); +if (ret <0 ) + goto out; +/* safe to set 1st arg (fd) to 0, as command is F_SETFL */ ret =vfs_fcntl (0 ,F_SETFL , h->f_flags &CKPT_SETFL_MASK , file);if (ret <0 )
include/linux/checkpoint_hdr.h +1 -0
@@ -320,6 +320,7 @@ struct ckpt_hdr_file {__s32 f_credref;__u64 f_pos;__u64 f_version; +__s32 f_secref; } __attribute__((aligned(8)));struct ckpt_hdr_file_generic {
include/linux/security.h +13 -0
@@ -554,6 +554,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)* created. * @file contains the file structure to secure. * Return 0 if the hook is successful and permission is granted. +* @file_restore_security: +* Allocate and attach a security structure to the file->f_security field +* during sys_restart(). +* @file contains the file structure to secure. +* @stored contains the checkpointed context. +* Return 0 if the hook is successful and permission is granted. * @file_free_security: * Deallocate and free any security structures stored in file->f_security. * @file contains the file structure being modified.
@@ -1494,6 +1500,7 @@ struct security_operations {int (*file_permission) (struct file *file,int mask);int (*file_alloc_security) (struct file *file); +int (*file_restore_security) (struct file *file,void *stored);void (*file_free_security) (struct file *file);int (*file_ioctl) (struct file *file,unsigned int cmd,unsigned long arg);
@@ -1761,6 +1768,7 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffervoid security_inode_getsecid (const struct inode *inode,u32 *secid);int security_file_permission (struct file *file,int mask);int security_file_alloc (struct file *file); +int security_file_restore (struct file *file,void *stored);void security_file_free (struct file *file);int security_file_ioctl (struct file *file,unsigned int cmd,unsigned long arg); int security_file_mmap(struct file *file, unsigned long reqprot,
@@ -2250,6 +2258,11 @@ static inline int security_file_alloc(struct file *file)return 0 ; } +static inline int security_file_restore (struct file *file,void *stored) +{ +return 0 ; +} +static inline void security_file_free (struct file *file) { }
security/capability.c +6 -0
@@ -320,6 +320,11 @@ static int cap_file_alloc_security(struct file *file)return 0 ; } +static int cap_file_restore_security (struct file *file,void *stored) +{ +return 0 ; +} +static void cap_file_free_security (struct file *file) { }
@@ -976,6 +981,7 @@ void security_fixup_ops(struct security_operations *ops)#endif set_to_cap_if_null (ops, file_permission);set_to_cap_if_null (ops, file_alloc_security); +set_to_cap_if_null (ops, file_restore_security);set_to_cap_if_null (ops, file_free_security);set_to_cap_if_null (ops, file_ioctl);set_to_cap_if_null (ops, file_mmap);
security/security.c +5 -0
@@ -628,6 +628,11 @@ int security_file_alloc(struct file *file)return security_ops->file_alloc_security (file); } +int security_file_restore (struct file *file,void *stored) +{ +return security_ops->file_restore_security (file, stored); +} +void security_file_free (struct file *file) { security_ops->file_free_security (file);
security/selinux/hooks.c +11 -0
@@ -2973,6 +2973,16 @@ static int selinux_file_alloc_security(struct file *file)return file_alloc_security (file); } +static int selinux_file_restore_security (struct file *file, +void *stored) +{ +/* +* TODO - actually restore from 'stored' subject to authorization +*/ +kfree (stored); +return file_alloc_security (file); +} +static void selinux_file_free_security (struct file *file) {file_free_security (file);
@@ -5566,6 +5576,7 @@ static struct security_operations selinux_ops = { .file_permission = selinux_file_permission, .file_alloc_security = selinux_file_alloc_security, + .file_restore_security = selinux_file_restore_security, .file_free_security = selinux_file_free_security, .file_ioctl = selinux_file_ioctl, .file_mmap = selinux_file_mmap,
security/smack/smack_lsm.c +25 -1
@@ -831,6 +831,30 @@ static int smack_file_alloc_security(struct file *file) }/** +* smack_file_restore_security - assign a file security blob +* @file: the object +* @stored: the label stored in the checkpoint file +* +* Returns 0 +*/ +static int smack_file_restore_security (struct file *file,void *stored) +{ +char *str =smk_import (stored,0 ); + +if (str ==NULL ) +return -EINVAL ; + + file->f_security =current_security (); +if (current_security () != str) { +if (!capable (CAP_MAC_ADMIN )) +return -EPERM ; + file->f_security = str; + } + +return 0 ; +} + +/** * smack_file_free_security - clear a file security blob * @file: the object *
@@ -1630,7 +1654,6 @@ static int smack_msg_msg_restore_security(struct msg_msg *msg, msg->security = str; }return 0 ; -return 0 ; }/**
@@ -2996,6 +3019,7 @@ struct security_operations smack_ops = { .file_permission = smack_file_permission, .file_alloc_security = smack_file_alloc_security, + .file_restore_security = smack_file_restore_security, .file_free_security = smack_file_free_security, .file_ioctl = smack_file_ioctl, .file_lock = smack_file_lock,
Signature · 7 lines
1.6.1 -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
A message that is not in the archive (sent off-list or not yet received): 20090610014704.GI5658-r/[email protected]
Re: [PATCH 10/10] cr: lsm: restore file->f_security
Quoted 33 lines · Serge E. Hallyn
file->f_credis the cred of the task which opened it.file->f_securitycan be separately set by the LSM. Checkpoint thefile->f_security, and at restart ask the LSM, usingsecurity_file_restore, based on the current task's context and the checkpointedf_security, whichf_securityto apply (or whether to refuse the restart altogether).For Smack, accept the checkpointed label if the restarting task has
CAP_MAC_ADMIN.For SELinux, I currently ignore the checkpointed label and call
file_alloc_security(). Do we want to have 'restore' permission for class file?Signed-off-by Serge E. Hallyn <serue-r/[email protected]>--- checkpoint/files.c | 33 +++++++++++++++++++++++++++++++++ include/linux/checkpoint_hdr.h | 1 + include/linux/security.h | 13 +++++++++++++ security/capability.c | 6 ++++++ security/security.c | 5 +++++ security/selinux/hooks.c | 11 +++++++++++ security/smack/smack_lsm.c | 26 +++++++++++++++++++++++++- 7 files changed, 94 insertions(+), 1 deletions(-)...
security/smack/smack_lsm.c +0
-0
security/smack/smack_lsm.c static int smack_file_alloc_security(struct file *file) · line 839
Quoted 9 lines
security/smack/smack_lsm.c +5
-0@@ -831,6 +831,30 @@ static int smack_file_alloc_security(struct file *file) }/** +* smack_file_restore_security - assign a file security blob +* @file: the object +* @stored: the label stored in the checkpoint file +* +* Returns 0
Or -EINVAL if the label is not acceptable
Quoted 23 lines
security/smack/smack_lsm.c +19
-0+*/ +static int smack_file_restore_security (struct file *file,void *stored) +{ +char *str =smk_import (stored,0 ); + +if (str ==NULL ) +return -EINVAL ; + + file->f_security =current_security (); +if (current_security () != str) { +if (!capable (CAP_MAC_ADMIN )) +return -EPERM ; + file->f_security = str; + } + +return 0 ; +} + +/** * smack_file_free_security - clear a file security blob * @file: the object *
security/smack/smack_lsm.c static int smack_msg_msg_restore_security(struct msg_msg *msg, · line 1657
Quoted 5 lines
security/smack/smack_lsm.c +0
-1@@ -1630,7 +1654,6 @@ static int smack_msg_msg_restore_security(struct msg_msg *msg, msg->security = str; }return 0 ; -return 0 ;
Looks like you caught that. Thank you
Quoted 12 lines
security/smack/smack_lsm.c +0
-0}/**
security/smack/smack_lsm.c +1
-0@@ -2996,6 +3019,7 @@ struct security_operations smack_ops = { .file_permission = smack_file_permission, .file_alloc_security = smack_file_alloc_security, + .file_restore_security = smack_file_restore_security, .file_free_security = smack_file_free_security, .file_ioctl = smack_file_ioctl, .file_lock = smack_file_lock,
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 10/10] cr: lsm: restore file->f_security
Quoted 8 lines · Casey Schaufler
security/smack/smack_lsm.c static int smack_msg_msg_restore_security(struct msg_msg *msg, · line 1657
Quoted 6 lines
security/smack/smack_lsm.c +0
-1@@ -1630,7 +1654,6 @@ static int smack_msg_msg_restore_security(struct msg_msg *msg, msg->security = str; }return 0 ; -return 0 ;Looks like you caught that. Thank you
Huh. No, I didn't :) I'm guessing that both the original problem and this accidental fix came about through my inexperience with resolving conflicts in git-rebase...
Thanks for taking a look, I will address all of your comments in the next posting.
For the next version I may split up the smack, selinux, and tomoyo hooks into separate patches from the core LSM patch (and nix the rather silly split of the security_file_restore hook) for easier review...
thanks,
-serge
Re: [PATCH 10/10] cr: lsm: restore file->f_security
In reply to a message not in the archiveQuoted 6 lines · Serge E. Hallyn
file->f_credis the cred of the task which opened it.file->f_securitycan be separately set by the LSM. Checkpoint thefile->f_security, and at restart ask the LSM, usingsecurity_file_restore, based on the current task's context and the checkpointedf_security, whichf_securityto apply (or whether to refuse the restart altogether).
Quoted 6 lines
For Smack, accept the checkpointed label if the restarting task has
CAP_MAC_ADMIN.For SELinux, I currently ignore the checkpointed label and call
file_alloc_security(). Do we want to have 'restore' permission for class file?
Yes - otherwise we'll end up with a restarted process that may not be able to access its open files.
Signature · 2 lines
Stephen Smalley National Security Agency