Commit c0ab6e56 authored by Casey Schaufler's avatar Casey Schaufler

Smack: Implement lock security mode

Linux file locking does not follow the same rules
as other mechanisms. Even though it is a write operation
a process can set a read lock on files which it has open
only for read access. Two programs with read access to
a file can use read locks to communicate.

This is not acceptable in a Mandatory Access Control
environment. Smack treats setting a read lock as the
write operation that it is. Unfortunately, many programs
assume that setting a read lock is a read operation.
These programs are unhappy in the Smack environment.

This patch introduces a new access mode (lock) to address
this problem. A process with lock access to a file can
set a read lock. A process with write access to a file can
set a read lock or a write lock. This prevents a situation
where processes are granted write access just so they can
set read locks.

Targeted for git://git.gitorious.org/smack-next/kernel.gitSigned-off-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
parent 5a5f2acf
...@@ -177,9 +177,13 @@ struct smk_port_label { ...@@ -177,9 +177,13 @@ struct smk_port_label {
#define SMACK_CIPSO_MAXCATNUM 184 /* 23 * 8 */ #define SMACK_CIPSO_MAXCATNUM 184 /* 23 * 8 */
/* /*
* Flag for transmute access * Flags for untraditional access modes.
* It shouldn't be necessary to avoid conflicts with definitions
* in fs.h, but do so anyway.
*/ */
#define MAY_TRANSMUTE 64 #define MAY_TRANSMUTE 0x00001000 /* Controls directory labeling */
#define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */
/* /*
* Just to make the common cases easier to deal with * Just to make the common cases easier to deal with
*/ */
...@@ -188,9 +192,9 @@ struct smk_port_label { ...@@ -188,9 +192,9 @@ struct smk_port_label {
#define MAY_NOT 0 #define MAY_NOT 0
/* /*
* Number of access types used by Smack (rwxat) * Number of access types used by Smack (rwxatl)
*/ */
#define SMK_NUM_ACCESS_TYPE 5 #define SMK_NUM_ACCESS_TYPE 6
/* SMACK data */ /* SMACK data */
struct smack_audit_data { struct smack_audit_data {
......
...@@ -84,6 +84,8 @@ int log_policy = SMACK_AUDIT_DENIED; ...@@ -84,6 +84,8 @@ int log_policy = SMACK_AUDIT_DENIED;
* *
* Do the object check first because that is more * Do the object check first because that is more
* likely to differ. * likely to differ.
*
* Allowing write access implies allowing locking.
*/ */
int smk_access_entry(char *subject_label, char *object_label, int smk_access_entry(char *subject_label, char *object_label,
struct list_head *rule_list) struct list_head *rule_list)
...@@ -99,6 +101,11 @@ int smk_access_entry(char *subject_label, char *object_label, ...@@ -99,6 +101,11 @@ int smk_access_entry(char *subject_label, char *object_label,
} }
} }
/*
* MAY_WRITE implies MAY_LOCK.
*/
if ((may & MAY_WRITE) == MAY_WRITE)
may |= MAY_LOCK;
return may; return may;
} }
...@@ -245,6 +252,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) ...@@ -245,6 +252,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
static inline void smack_str_from_perm(char *string, int access) static inline void smack_str_from_perm(char *string, int access)
{ {
int i = 0; int i = 0;
if (access & MAY_READ) if (access & MAY_READ)
string[i++] = 'r'; string[i++] = 'r';
if (access & MAY_WRITE) if (access & MAY_WRITE)
...@@ -255,6 +263,8 @@ static inline void smack_str_from_perm(char *string, int access) ...@@ -255,6 +263,8 @@ static inline void smack_str_from_perm(char *string, int access)
string[i++] = 'a'; string[i++] = 'a';
if (access & MAY_TRANSMUTE) if (access & MAY_TRANSMUTE)
string[i++] = 't'; string[i++] = 't';
if (access & MAY_LOCK)
string[i++] = 'l';
string[i] = '\0'; string[i] = '\0';
} }
/** /**
......
...@@ -1146,7 +1146,7 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd, ...@@ -1146,7 +1146,7 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
* @file: the object * @file: the object
* @cmd: unused * @cmd: unused
* *
* Returns 0 if current has write access, error code otherwise * Returns 0 if current has lock access, error code otherwise
*/ */
static int smack_file_lock(struct file *file, unsigned int cmd) static int smack_file_lock(struct file *file, unsigned int cmd)
{ {
...@@ -1154,7 +1154,7 @@ static int smack_file_lock(struct file *file, unsigned int cmd) ...@@ -1154,7 +1154,7 @@ static int smack_file_lock(struct file *file, unsigned int cmd)
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, file->f_path); smk_ad_setfield_u_fs_path(&ad, file->f_path);
return smk_curacc(file->f_security, MAY_WRITE, &ad); return smk_curacc(file->f_security, MAY_LOCK, &ad);
} }
/** /**
...@@ -1178,8 +1178,13 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, ...@@ -1178,8 +1178,13 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
switch (cmd) { switch (cmd) {
case F_GETLK: case F_GETLK:
break;
case F_SETLK: case F_SETLK:
case F_SETLKW: case F_SETLKW:
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, file->f_path);
rc = smk_curacc(file->f_security, MAY_LOCK, &ad);
break;
case F_SETOWN: case F_SETOWN:
case F_SETSIG: case F_SETSIG:
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
......
...@@ -139,7 +139,7 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION; ...@@ -139,7 +139,7 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION;
* SMK_LOADLEN: Smack rule length * SMK_LOADLEN: Smack rule length
*/ */
#define SMK_OACCESS "rwxa" #define SMK_OACCESS "rwxa"
#define SMK_ACCESS "rwxat" #define SMK_ACCESS "rwxatl"
#define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1) #define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1)
#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
#define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN) #define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN)
...@@ -282,6 +282,10 @@ static int smk_perm_from_str(const char *string) ...@@ -282,6 +282,10 @@ static int smk_perm_from_str(const char *string)
case 'T': case 'T':
perm |= MAY_TRANSMUTE; perm |= MAY_TRANSMUTE;
break; break;
case 'l':
case 'L':
perm |= MAY_LOCK;
break;
default: default:
return perm; return perm;
} }
...@@ -452,7 +456,7 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, ...@@ -452,7 +456,7 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
/* /*
* Minor hack for backward compatibility * Minor hack for backward compatibility
*/ */
if (count != SMK_OLOADLEN && count != SMK_LOADLEN) if (count < SMK_OLOADLEN || count > SMK_LOADLEN)
return -EINVAL; return -EINVAL;
} else { } else {
if (count >= PAGE_SIZE) { if (count >= PAGE_SIZE) {
...@@ -592,6 +596,8 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) ...@@ -592,6 +596,8 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
seq_putc(s, 'a'); seq_putc(s, 'a');
if (srp->smk_access & MAY_TRANSMUTE) if (srp->smk_access & MAY_TRANSMUTE)
seq_putc(s, 't'); seq_putc(s, 't');
if (srp->smk_access & MAY_LOCK)
seq_putc(s, 'l');
seq_putc(s, '\n'); seq_putc(s, '\n');
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment