mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 14:04:27 -04:00
smack: fix incorrect task context in smack_msg_queue_msgrcv
The smack_msg_queue_msgrcv() function incorrectly checks
the permissions of the 'current' task instead of the
'target' task.
In the msgsnd() syscall path, if a receiver is already waiting,
the pipelined_send() optimization is used to push the message
directly to the receiver task:
ipc/msg.c`pipelined_send():
` smp_store_release(&msr->r_msg, msg)
In this case, the 'sender' (current) task performs the check
on behalf of the 'receiver' task (msr->r_tsk, passed as the
'target' parameter):
ipc/msg.c`pipelined_send():
` security_msg_queue_msgrcv(,, target := msr->r_tsk,,)
However, smack_msg_queue_msgrcv() ignores the 'target' and
checks 'current':
smack_msg_queue_msgrcv(…)
` smk_curacc_msq(isp, MAY_READWRITE); // current task
'current' MAY satisfy smack_msg_queue_msgrcv r/w requirement,
but 'target' (the receiver task) might NOT;
as a result, an unauthorized receiver gets the message,
violating MAC policy.
Test:
1) create a sysv message queue with label “foo”
2) echo "bar foo r" >/smack/load2
3) msgrcv(,,,0,MSG_NOERROR) in "bar"-labeled task.
The task is waiting for the messages ...
4) msgsnd() from a "foo"-labeled task:
"bar"-labeled task gets the message.
This patch fixes the issue by checking permission on the
'target' task instead of 'current'.
(2008-02-04, Casey Schaufler)
Fixes: e114e47377 ("Smack: Simplified Mandatory Access Control Kernel")
Signed-off-by: Konstantin Andreev <andreev@swemel.ru>
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
This commit is contained in:
committed by
Casey Schaufler
parent
3cef22655c
commit
fba3d32825
@@ -130,12 +130,13 @@ static int smk_bu_note(char *note, struct smack_known *sskp,
|
||||
#define smk_bu_note(note, sskp, oskp, mode, RC) (RC)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
static int smk_bu_current(char *note, struct smack_known *oskp,
|
||||
int mode, int rc)
|
||||
static int
|
||||
smk_bu_tsk_to_obj(struct task_struct *tsk, const struct task_smack *tsp,
|
||||
char *note, struct smack_known *oskp, int mode, int rc)
|
||||
{
|
||||
struct task_smack *tsp = smack_cred(current_cred());
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
char acc[SMK_NUM_ACCESS_TYPE + 1];
|
||||
char comm[TASK_COMM_LEN];
|
||||
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
@@ -143,14 +144,22 @@ static int smk_bu_current(char *note, struct smack_known *oskp,
|
||||
rc = 0;
|
||||
|
||||
smk_bu_mode(mode, acc);
|
||||
|
||||
pr_info("Smack %s: (%s %s %s) %s %s\n", smk_bu_mess[rc],
|
||||
tsp->smk_task->smk_known, oskp->smk_known,
|
||||
acc, current->comm, note);
|
||||
smk_of_task(tsp)->smk_known, oskp->smk_known,
|
||||
acc, get_task_comm(comm, tsk), note);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define smk_bu_current(note, oskp, mode, RC) (RC)
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int smk_bu_current(char *note, struct smack_known *oskp,
|
||||
int mode, int rc)
|
||||
{
|
||||
return smk_bu_tsk_to_obj(current, smack_cred(current_cred()),
|
||||
note, oskp, mode, rc);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
static int smk_bu_task(struct task_struct *otp, int mode, int rc)
|
||||
@@ -3353,14 +3362,20 @@ static int smack_sem_semop(struct kern_ipc_perm *isp, struct sembuf *sops,
|
||||
}
|
||||
|
||||
/**
|
||||
* smk_curacc_msq : helper to check if current has access on msq
|
||||
* @isp : the msq
|
||||
* smk_tskacc_msq : helper to check if tsk has access on msq
|
||||
* @tsk: the task that requests access
|
||||
* @isp : the sysv msg queue permissions
|
||||
* @access : access requested
|
||||
*
|
||||
* return 0 if current has access, error otherwise
|
||||
* return 0 if tsk has access, error otherwise
|
||||
*/
|
||||
static int smk_curacc_msq(struct kern_ipc_perm *isp, int access)
|
||||
static int
|
||||
smk_tskacc_msq(struct task_struct *tsk, struct kern_ipc_perm *isp, int access)
|
||||
{
|
||||
const bool tsk_is_current = (tsk == current);
|
||||
const struct cred * const tsk_cred =
|
||||
(tsk_is_current ? current_cred() : get_task_cred(tsk));
|
||||
struct task_smack * const tsp = smack_cred(tsk_cred);
|
||||
struct smack_known *msp = smack_of_ipc(isp);
|
||||
struct smk_audit_info ad;
|
||||
int rc;
|
||||
@@ -3369,11 +3384,25 @@ static int smk_curacc_msq(struct kern_ipc_perm *isp, int access)
|
||||
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
|
||||
ad.a.u.ipc_id = isp->id;
|
||||
#endif
|
||||
rc = smk_curacc(msp, access, &ad);
|
||||
rc = smk_bu_current("msq", msp, access, rc);
|
||||
rc = smk_tskacc(tsp, msp, access, &ad);
|
||||
rc = smk_bu_tsk_to_obj(tsk, tsp, "msq", msp, access, rc);
|
||||
if (!tsk_is_current)
|
||||
put_cred(tsk_cred);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* smk_curacc_msq : helper to check if current has access on msq
|
||||
* @isp : the sysv msg queue permissions
|
||||
* @access : access requested
|
||||
*
|
||||
* return 0 if current has access, error otherwise
|
||||
*/
|
||||
static int smk_curacc_msq(struct kern_ipc_perm *isp, int access)
|
||||
{
|
||||
return smk_tskacc_msq(current, isp, access);
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_msg_queue_associate - Smack access check for msg_queue
|
||||
* @isp: the object
|
||||
@@ -3441,21 +3470,21 @@ static int smack_msg_queue_msgsnd(struct kern_ipc_perm *isp, struct msg_msg *msg
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_msg_queue_msgrcv - Smack access check for msg_queue
|
||||
* smack_msg_queue_msgrcv - check it target has r/w access to msg_queue
|
||||
* @isp: the object
|
||||
* @msg: unused
|
||||
* @target: unused
|
||||
* @target: the task that msgrcv() from the queue
|
||||
* @type: unused
|
||||
* @mode: unused
|
||||
*
|
||||
* Returns 0 if current has read and write access, error code otherwise
|
||||
* Returns 0 if target has read and write access, error code otherwise
|
||||
*/
|
||||
static int smack_msg_queue_msgrcv(struct kern_ipc_perm *isp,
|
||||
struct msg_msg *msg,
|
||||
struct task_struct *target, long type,
|
||||
int mode)
|
||||
{
|
||||
return smk_curacc_msq(isp, MAY_READWRITE);
|
||||
return smk_tskacc_msq(target, isp, MAY_READWRITE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user