CRED: Make inode_has_perm() and file_has_perm() take a cred pointer

Make inode_has_perm() and file_has_perm() take a cred pointer rather than a
task pointer.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
David Howells 2008-11-14 10:39:21 +11:00 committed by James Morris
parent 6cc88bc45c
commit 88e67f3b88
1 changed files with 92 additions and 48 deletions

View File

@ -172,17 +172,26 @@ static int cred_alloc_security(struct cred *cred)
return 0; return 0;
} }
/*
* get the security ID of a set of credentials
*/
static inline u32 cred_sid(const struct cred *cred)
{
const struct task_security_struct *tsec;
tsec = cred->security;
return tsec->sid;
}
/* /*
* get the security ID of a task * get the security ID of a task
*/ */
static inline u32 task_sid(const struct task_struct *task) static inline u32 task_sid(const struct task_struct *task)
{ {
const struct task_security_struct *tsec;
u32 sid; u32 sid;
rcu_read_lock(); rcu_read_lock();
tsec = __task_cred(task)->security; sid = cred_sid(__task_cred(task));
sid = tsec->sid;
rcu_read_unlock(); rcu_read_unlock();
return sid; return sid;
} }
@ -197,6 +206,8 @@ static inline u32 current_sid(void)
return tsec->sid; return tsec->sid;
} }
/* Allocate and free functions for each kind of security blob. */
static int inode_alloc_security(struct inode *inode) static int inode_alloc_security(struct inode *inode)
{ {
struct inode_security_struct *isec; struct inode_security_struct *isec;
@ -1368,7 +1379,7 @@ static inline u32 signal_to_av(int sig)
} }
/* /*
* Check permission betweeen a pair of tasks, e.g. signal checks, * Check permission between a pair of tasks, e.g. signal checks,
* fork check, ptrace check, etc. * fork check, ptrace check, etc.
* tsk1 is the actor and tsk2 is the target * tsk1 is the actor and tsk2 is the target
*/ */
@ -1437,7 +1448,7 @@ static int task_has_system(struct task_struct *tsk,
/* Check whether a task has a particular permission to an inode. /* Check whether a task has a particular permission to an inode.
The 'adp' parameter is optional and allows other audit The 'adp' parameter is optional and allows other audit
data to be passed (e.g. the dentry). */ data to be passed (e.g. the dentry). */
static int inode_has_perm(struct task_struct *tsk, static int inode_has_perm(const struct cred *cred,
struct inode *inode, struct inode *inode,
u32 perms, u32 perms,
struct avc_audit_data *adp) struct avc_audit_data *adp)
@ -1449,7 +1460,7 @@ static int inode_has_perm(struct task_struct *tsk,
if (unlikely(IS_PRIVATE(inode))) if (unlikely(IS_PRIVATE(inode)))
return 0; return 0;
sid = task_sid(tsk); sid = cred_sid(cred);
isec = inode->i_security; isec = inode->i_security;
if (!adp) { if (!adp) {
@ -1464,17 +1475,18 @@ static int inode_has_perm(struct task_struct *tsk,
/* Same as inode_has_perm, but pass explicit audit data containing /* Same as inode_has_perm, but pass explicit audit data containing
the dentry to help the auditing code to more easily generate the the dentry to help the auditing code to more easily generate the
pathname if needed. */ pathname if needed. */
static inline int dentry_has_perm(struct task_struct *tsk, static inline int dentry_has_perm(const struct cred *cred,
struct vfsmount *mnt, struct vfsmount *mnt,
struct dentry *dentry, struct dentry *dentry,
u32 av) u32 av)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct avc_audit_data ad; struct avc_audit_data ad;
AVC_AUDIT_DATA_INIT(&ad, FS); AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.mnt = mnt; ad.u.fs.path.mnt = mnt;
ad.u.fs.path.dentry = dentry; ad.u.fs.path.dentry = dentry;
return inode_has_perm(tsk, inode, av, &ad); return inode_has_perm(cred, inode, av, &ad);
} }
/* Check whether a task can use an open file descriptor to /* Check whether a task can use an open file descriptor to
@ -1485,14 +1497,14 @@ static inline int dentry_has_perm(struct task_struct *tsk,
has the same SID as the process. If av is zero, then has the same SID as the process. If av is zero, then
access to the file is not checked, e.g. for cases access to the file is not checked, e.g. for cases
where only the descriptor is affected like seek. */ where only the descriptor is affected like seek. */
static int file_has_perm(struct task_struct *tsk, static int file_has_perm(const struct cred *cred,
struct file *file, struct file *file,
u32 av) u32 av)
{ {
struct file_security_struct *fsec = file->f_security; struct file_security_struct *fsec = file->f_security;
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
struct avc_audit_data ad; struct avc_audit_data ad;
u32 sid = task_sid(tsk); u32 sid = cred_sid(cred);
int rc; int rc;
AVC_AUDIT_DATA_INIT(&ad, FS); AVC_AUDIT_DATA_INIT(&ad, FS);
@ -1504,14 +1516,16 @@ static int file_has_perm(struct task_struct *tsk,
FD__USE, FD__USE,
&ad); &ad);
if (rc) if (rc)
return rc; goto out;
} }
/* av is zero if only checking access to the descriptor. */ /* av is zero if only checking access to the descriptor. */
rc = 0;
if (av) if (av)
return inode_has_perm(tsk, inode, av, &ad); rc = inode_has_perm(cred, inode, av, &ad);
return 0; out:
return rc;
} }
/* Check whether a task can create a file. */ /* Check whether a task can create a file. */
@ -1670,13 +1684,13 @@ static inline int may_rename(struct inode *old_dir,
} }
/* Check whether a task can perform a filesystem operation. */ /* Check whether a task can perform a filesystem operation. */
static int superblock_has_perm(struct task_struct *tsk, static int superblock_has_perm(const struct cred *cred,
struct super_block *sb, struct super_block *sb,
u32 perms, u32 perms,
struct avc_audit_data *ad) struct avc_audit_data *ad)
{ {
struct superblock_security_struct *sbsec; struct superblock_security_struct *sbsec;
u32 sid = task_sid(tsk); u32 sid = cred_sid(cred);
sbsec = sb->s_security; sbsec = sb->s_security;
return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad); return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
@ -1919,6 +1933,7 @@ static int selinux_sysctl(ctl_table *table, int op)
static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
{ {
const struct cred *cred = current_cred();
int rc = 0; int rc = 0;
if (!sb) if (!sb)
@ -1930,14 +1945,12 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
case Q_QUOTAOFF: case Q_QUOTAOFF:
case Q_SETINFO: case Q_SETINFO:
case Q_SETQUOTA: case Q_SETQUOTA:
rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAMOD, rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
NULL);
break; break;
case Q_GETFMT: case Q_GETFMT:
case Q_GETINFO: case Q_GETINFO:
case Q_GETQUOTA: case Q_GETQUOTA:
rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAGET, rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
NULL);
break; break;
default: default:
rc = 0; /* let the kernel handle invalid cmds */ rc = 0; /* let the kernel handle invalid cmds */
@ -1948,7 +1961,9 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
static int selinux_quota_on(struct dentry *dentry) static int selinux_quota_on(struct dentry *dentry)
{ {
return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON); const struct cred *cred = current_cred();
return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON);
} }
static int selinux_syslog(int type) static int selinux_syslog(int type)
@ -2137,6 +2152,7 @@ extern struct dentry *selinux_null;
/* Derived from fs/exec.c:flush_old_files. */ /* Derived from fs/exec.c:flush_old_files. */
static inline void flush_unauthorized_files(struct files_struct *files) static inline void flush_unauthorized_files(struct files_struct *files)
{ {
const struct cred *cred = current_cred();
struct avc_audit_data ad; struct avc_audit_data ad;
struct file *file, *devnull = NULL; struct file *file, *devnull = NULL;
struct tty_struct *tty; struct tty_struct *tty;
@ -2157,7 +2173,7 @@ static inline void flush_unauthorized_files(struct files_struct *files)
interested in the inode-based check here. */ interested in the inode-based check here. */
file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list); file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list);
inode = file->f_path.dentry->d_inode; inode = file->f_path.dentry->d_inode;
if (inode_has_perm(current, inode, if (inode_has_perm(cred, inode,
FILE__READ | FILE__WRITE, NULL)) { FILE__READ | FILE__WRITE, NULL)) {
drop_tty = 1; drop_tty = 1;
} }
@ -2192,7 +2208,7 @@ static inline void flush_unauthorized_files(struct files_struct *files)
file = fget(i); file = fget(i);
if (!file) if (!file)
continue; continue;
if (file_has_perm(current, if (file_has_perm(cred,
file, file,
file_to_av(file))) { file_to_av(file))) {
sys_close(i); sys_close(i);
@ -2465,6 +2481,7 @@ out:
static int selinux_sb_kern_mount(struct super_block *sb, void *data) static int selinux_sb_kern_mount(struct super_block *sb, void *data)
{ {
const struct cred *cred = current_cred();
struct avc_audit_data ad; struct avc_audit_data ad;
int rc; int rc;
@ -2474,16 +2491,17 @@ static int selinux_sb_kern_mount(struct super_block *sb, void *data)
AVC_AUDIT_DATA_INIT(&ad, FS); AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = sb->s_root; ad.u.fs.path.dentry = sb->s_root;
return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad); return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
} }
static int selinux_sb_statfs(struct dentry *dentry) static int selinux_sb_statfs(struct dentry *dentry)
{ {
const struct cred *cred = current_cred();
struct avc_audit_data ad; struct avc_audit_data ad;
AVC_AUDIT_DATA_INIT(&ad, FS); AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = dentry->d_sb->s_root; ad.u.fs.path.dentry = dentry->d_sb->s_root;
return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad); return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
} }
static int selinux_mount(char *dev_name, static int selinux_mount(char *dev_name,
@ -2492,6 +2510,7 @@ static int selinux_mount(char *dev_name,
unsigned long flags, unsigned long flags,
void *data) void *data)
{ {
const struct cred *cred = current_cred();
int rc; int rc;
rc = secondary_ops->sb_mount(dev_name, path, type, flags, data); rc = secondary_ops->sb_mount(dev_name, path, type, flags, data);
@ -2499,22 +2518,23 @@ static int selinux_mount(char *dev_name,
return rc; return rc;
if (flags & MS_REMOUNT) if (flags & MS_REMOUNT)
return superblock_has_perm(current, path->mnt->mnt_sb, return superblock_has_perm(cred, path->mnt->mnt_sb,
FILESYSTEM__REMOUNT, NULL); FILESYSTEM__REMOUNT, NULL);
else else
return dentry_has_perm(current, path->mnt, path->dentry, return dentry_has_perm(cred, path->mnt, path->dentry,
FILE__MOUNTON); FILE__MOUNTON);
} }
static int selinux_umount(struct vfsmount *mnt, int flags) static int selinux_umount(struct vfsmount *mnt, int flags)
{ {
const struct cred *cred = current_cred();
int rc; int rc;
rc = secondary_ops->sb_umount(mnt, flags); rc = secondary_ops->sb_umount(mnt, flags);
if (rc) if (rc)
return rc; return rc;
return superblock_has_perm(current, mnt->mnt_sb, return superblock_has_perm(cred, mnt->mnt_sb,
FILESYSTEM__UNMOUNT, NULL); FILESYSTEM__UNMOUNT, NULL);
} }
@ -2652,21 +2672,25 @@ static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dent
static int selinux_inode_readlink(struct dentry *dentry) static int selinux_inode_readlink(struct dentry *dentry)
{ {
return dentry_has_perm(current, NULL, dentry, FILE__READ); const struct cred *cred = current_cred();
return dentry_has_perm(cred, NULL, dentry, FILE__READ);
} }
static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata) static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
{ {
const struct cred *cred = current_cred();
int rc; int rc;
rc = secondary_ops->inode_follow_link(dentry, nameidata); rc = secondary_ops->inode_follow_link(dentry, nameidata);
if (rc) if (rc)
return rc; return rc;
return dentry_has_perm(current, NULL, dentry, FILE__READ); return dentry_has_perm(cred, NULL, dentry, FILE__READ);
} }
static int selinux_inode_permission(struct inode *inode, int mask) static int selinux_inode_permission(struct inode *inode, int mask)
{ {
const struct cred *cred = current_cred();
int rc; int rc;
rc = secondary_ops->inode_permission(inode, mask); rc = secondary_ops->inode_permission(inode, mask);
@ -2678,12 +2702,13 @@ static int selinux_inode_permission(struct inode *inode, int mask)
return 0; return 0;
} }
return inode_has_perm(current, inode, return inode_has_perm(cred, inode,
file_mask_to_av(inode->i_mode, mask), NULL); file_mask_to_av(inode->i_mode, mask), NULL);
} }
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
{ {
const struct cred *cred = current_cred();
int rc; int rc;
rc = secondary_ops->inode_setattr(dentry, iattr); rc = secondary_ops->inode_setattr(dentry, iattr);
@ -2695,18 +2720,22 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
ATTR_ATIME_SET | ATTR_MTIME_SET)) ATTR_ATIME_SET | ATTR_MTIME_SET))
return dentry_has_perm(current, NULL, dentry, FILE__SETATTR); return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR);
return dentry_has_perm(current, NULL, dentry, FILE__WRITE); return dentry_has_perm(cred, NULL, dentry, FILE__WRITE);
} }
static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
{ {
return dentry_has_perm(current, mnt, dentry, FILE__GETATTR); const struct cred *cred = current_cred();
return dentry_has_perm(cred, mnt, dentry, FILE__GETATTR);
} }
static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
{ {
const struct cred *cred = current_cred();
if (!strncmp(name, XATTR_SECURITY_PREFIX, if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof XATTR_SECURITY_PREFIX - 1)) { sizeof XATTR_SECURITY_PREFIX - 1)) {
if (!strcmp(name, XATTR_NAME_CAPS)) { if (!strcmp(name, XATTR_NAME_CAPS)) {
@ -2721,7 +2750,7 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
/* Not an attribute we recognize, so just check the /* Not an attribute we recognize, so just check the
ordinary setattr permission. */ ordinary setattr permission. */
return dentry_has_perm(current, NULL, dentry, FILE__SETATTR); return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR);
} }
static int selinux_inode_setxattr(struct dentry *dentry, const char *name, static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
@ -2806,12 +2835,16 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
static int selinux_inode_getxattr(struct dentry *dentry, const char *name) static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
{ {
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR); const struct cred *cred = current_cred();
return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR);
} }
static int selinux_inode_listxattr(struct dentry *dentry) static int selinux_inode_listxattr(struct dentry *dentry)
{ {
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR); const struct cred *cred = current_cred();
return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR);
} }
static int selinux_inode_removexattr(struct dentry *dentry, const char *name) static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
@ -2915,6 +2948,7 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
static int selinux_revalidate_file_permission(struct file *file, int mask) static int selinux_revalidate_file_permission(struct file *file, int mask)
{ {
const struct cred *cred = current_cred();
int rc; int rc;
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
@ -2927,7 +2961,7 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
mask |= MAY_APPEND; mask |= MAY_APPEND;
rc = file_has_perm(current, file, rc = file_has_perm(cred, file,
file_mask_to_av(inode->i_mode, mask)); file_mask_to_av(inode->i_mode, mask));
if (rc) if (rc)
return rc; return rc;
@ -2967,6 +3001,7 @@ static void selinux_file_free_security(struct file *file)
static int selinux_file_ioctl(struct file *file, unsigned int cmd, static int selinux_file_ioctl(struct file *file, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
const struct cred *cred = current_cred();
u32 av = 0; u32 av = 0;
if (_IOC_DIR(cmd) & _IOC_WRITE) if (_IOC_DIR(cmd) & _IOC_WRITE)
@ -2976,11 +3011,13 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
if (!av) if (!av)
av = FILE__IOCTL; av = FILE__IOCTL;
return file_has_perm(current, file, av); return file_has_perm(cred, file, av);
} }
static int file_map_prot_check(struct file *file, unsigned long prot, int shared) static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
{ {
const struct cred *cred = current_cred();
#ifndef CONFIG_PPC32 #ifndef CONFIG_PPC32
if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
/* /*
@ -3005,7 +3042,7 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
if (prot & PROT_EXEC) if (prot & PROT_EXEC)
av |= FILE__EXECUTE; av |= FILE__EXECUTE;
return file_has_perm(current, file, av); return file_has_perm(cred, file, av);
} }
return 0; return 0;
} }
@ -3034,6 +3071,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
unsigned long reqprot, unsigned long reqprot,
unsigned long prot) unsigned long prot)
{ {
const struct cred *cred = current_cred();
int rc; int rc;
rc = secondary_ops->file_mprotect(vma, reqprot, prot); rc = secondary_ops->file_mprotect(vma, reqprot, prot);
@ -3062,7 +3100,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
* modified content. This typically should only * modified content. This typically should only
* occur for text relocations. * occur for text relocations.
*/ */
rc = file_has_perm(current, vma->vm_file, rc = file_has_perm(cred, vma->vm_file,
FILE__EXECMOD); FILE__EXECMOD);
} }
if (rc) if (rc)
@ -3075,12 +3113,15 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
static int selinux_file_lock(struct file *file, unsigned int cmd) static int selinux_file_lock(struct file *file, unsigned int cmd)
{ {
return file_has_perm(current, file, FILE__LOCK); const struct cred *cred = current_cred();
return file_has_perm(cred, file, FILE__LOCK);
} }
static int selinux_file_fcntl(struct file *file, unsigned int cmd, static int selinux_file_fcntl(struct file *file, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
const struct cred *cred = current_cred();
int err = 0; int err = 0;
switch (cmd) { switch (cmd) {
@ -3091,7 +3132,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
} }
if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) { if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
err = file_has_perm(current, file, FILE__WRITE); err = file_has_perm(cred, file, FILE__WRITE);
break; break;
} }
/* fall through */ /* fall through */
@ -3101,7 +3142,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
case F_GETOWN: case F_GETOWN:
case F_GETSIG: case F_GETSIG:
/* Just check FD__USE permission */ /* Just check FD__USE permission */
err = file_has_perm(current, file, 0); err = file_has_perm(cred, file, 0);
break; break;
case F_GETLK: case F_GETLK:
case F_SETLK: case F_SETLK:
@ -3115,7 +3156,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
err = -EINVAL; err = -EINVAL;
break; break;
} }
err = file_has_perm(current, file, FILE__LOCK); err = file_has_perm(cred, file, FILE__LOCK);
break; break;
} }
@ -3156,11 +3197,14 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
static int selinux_file_receive(struct file *file) static int selinux_file_receive(struct file *file)
{ {
return file_has_perm(current, file, file_to_av(file)); const struct cred *cred = current_cred();
return file_has_perm(cred, file, file_to_av(file));
} }
static int selinux_dentry_open(struct file *file) static int selinux_dentry_open(struct file *file)
{ {
const struct cred *cred = current_cred();
struct file_security_struct *fsec; struct file_security_struct *fsec;
struct inode *inode; struct inode *inode;
struct inode_security_struct *isec; struct inode_security_struct *isec;
@ -3184,7 +3228,7 @@ static int selinux_dentry_open(struct file *file)
* new inode label or new policy. * new inode label or new policy.
* This check is not redundant - do not remove. * This check is not redundant - do not remove.
*/ */
return inode_has_perm(current, inode, open_file_to_av(file), NULL); return inode_has_perm(cred, inode, open_file_to_av(file), NULL);
} }
/* task security operations */ /* task security operations */