diff options
author | Casey Schaufler <casey@schaufler-ca.com> | 2013-10-11 21:06:39 -0400 |
---|---|---|
committer | Casey Schaufler <casey@schaufler-ca.com> | 2013-10-18 12:39:33 -0400 |
commit | c0ab6e56dcb7ca9903d460247cb464e769ae6e77 (patch) | |
tree | 52da39cb2798c0a4276d0d23fa3b4f1dbcd732f2 /security | |
parent | 5a5f2acfd04269e2e0958067216b68ff461c285c (diff) |
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.git
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security')
-rw-r--r-- | security/smack/smack.h | 12 | ||||
-rw-r--r-- | security/smack/smack_access.c | 10 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 9 | ||||
-rw-r--r-- | security/smack/smackfs.c | 10 |
4 files changed, 33 insertions, 8 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h index 076b8e8a51ab..364cc64fce71 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -177,9 +177,13 @@ struct smk_port_label { | |||
177 | #define SMACK_CIPSO_MAXCATNUM 184 /* 23 * 8 */ | 177 | #define SMACK_CIPSO_MAXCATNUM 184 /* 23 * 8 */ |
178 | 178 | ||
179 | /* | 179 | /* |
180 | * Flag for transmute access | 180 | * Flags for untraditional access modes. |
181 | * It shouldn't be necessary to avoid conflicts with definitions | ||
182 | * in fs.h, but do so anyway. | ||
181 | */ | 183 | */ |
182 | #define MAY_TRANSMUTE 64 | 184 | #define MAY_TRANSMUTE 0x00001000 /* Controls directory labeling */ |
185 | #define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */ | ||
186 | |||
183 | /* | 187 | /* |
184 | * Just to make the common cases easier to deal with | 188 | * Just to make the common cases easier to deal with |
185 | */ | 189 | */ |
@@ -188,9 +192,9 @@ struct smk_port_label { | |||
188 | #define MAY_NOT 0 | 192 | #define MAY_NOT 0 |
189 | 193 | ||
190 | /* | 194 | /* |
191 | * Number of access types used by Smack (rwxat) | 195 | * Number of access types used by Smack (rwxatl) |
192 | */ | 196 | */ |
193 | #define SMK_NUM_ACCESS_TYPE 5 | 197 | #define SMK_NUM_ACCESS_TYPE 6 |
194 | 198 | ||
195 | /* SMACK data */ | 199 | /* SMACK data */ |
196 | struct smack_audit_data { | 200 | struct smack_audit_data { |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index b3b59b1e93d6..14293cd9b1e5 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -84,6 +84,8 @@ int log_policy = SMACK_AUDIT_DENIED; | |||
84 | * | 84 | * |
85 | * Do the object check first because that is more | 85 | * Do the object check first because that is more |
86 | * likely to differ. | 86 | * likely to differ. |
87 | * | ||
88 | * Allowing write access implies allowing locking. | ||
87 | */ | 89 | */ |
88 | int smk_access_entry(char *subject_label, char *object_label, | 90 | int smk_access_entry(char *subject_label, char *object_label, |
89 | struct list_head *rule_list) | 91 | struct list_head *rule_list) |
@@ -99,6 +101,11 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
99 | } | 101 | } |
100 | } | 102 | } |
101 | 103 | ||
104 | /* | ||
105 | * MAY_WRITE implies MAY_LOCK. | ||
106 | */ | ||
107 | if ((may & MAY_WRITE) == MAY_WRITE) | ||
108 | may |= MAY_LOCK; | ||
102 | return may; | 109 | return may; |
103 | } | 110 | } |
104 | 111 | ||
@@ -245,6 +252,7 @@ out_audit: | |||
245 | static inline void smack_str_from_perm(char *string, int access) | 252 | static inline void smack_str_from_perm(char *string, int access) |
246 | { | 253 | { |
247 | int i = 0; | 254 | int i = 0; |
255 | |||
248 | if (access & MAY_READ) | 256 | if (access & MAY_READ) |
249 | string[i++] = 'r'; | 257 | string[i++] = 'r'; |
250 | if (access & MAY_WRITE) | 258 | if (access & MAY_WRITE) |
@@ -255,6 +263,8 @@ static inline void smack_str_from_perm(char *string, int access) | |||
255 | string[i++] = 'a'; | 263 | string[i++] = 'a'; |
256 | if (access & MAY_TRANSMUTE) | 264 | if (access & MAY_TRANSMUTE) |
257 | string[i++] = 't'; | 265 | string[i++] = 't'; |
266 | if (access & MAY_LOCK) | ||
267 | string[i++] = 'l'; | ||
258 | string[i] = '\0'; | 268 | string[i] = '\0'; |
259 | } | 269 | } |
260 | /** | 270 | /** |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 8825375cc031..88d366e55793 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -1146,7 +1146,7 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd, | |||
1146 | * @file: the object | 1146 | * @file: the object |
1147 | * @cmd: unused | 1147 | * @cmd: unused |
1148 | * | 1148 | * |
1149 | * Returns 0 if current has write access, error code otherwise | 1149 | * Returns 0 if current has lock access, error code otherwise |
1150 | */ | 1150 | */ |
1151 | static int smack_file_lock(struct file *file, unsigned int cmd) | 1151 | static int smack_file_lock(struct file *file, unsigned int cmd) |
1152 | { | 1152 | { |
@@ -1154,7 +1154,7 @@ static int smack_file_lock(struct file *file, unsigned int cmd) | |||
1154 | 1154 | ||
1155 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1155 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1156 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1156 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1157 | return smk_curacc(file->f_security, MAY_WRITE, &ad); | 1157 | return smk_curacc(file->f_security, MAY_LOCK, &ad); |
1158 | } | 1158 | } |
1159 | 1159 | ||
1160 | /** | 1160 | /** |
@@ -1178,8 +1178,13 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1178 | 1178 | ||
1179 | switch (cmd) { | 1179 | switch (cmd) { |
1180 | case F_GETLK: | 1180 | case F_GETLK: |
1181 | break; | ||
1181 | case F_SETLK: | 1182 | case F_SETLK: |
1182 | case F_SETLKW: | 1183 | case F_SETLKW: |
1184 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
1185 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | ||
1186 | rc = smk_curacc(file->f_security, MAY_LOCK, &ad); | ||
1187 | break; | ||
1183 | case F_SETOWN: | 1188 | case F_SETOWN: |
1184 | case F_SETSIG: | 1189 | case F_SETSIG: |
1185 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1190 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 80f4b4a45725..160aa08e3cd5 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -139,7 +139,7 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION; | |||
139 | * SMK_LOADLEN: Smack rule length | 139 | * SMK_LOADLEN: Smack rule length |
140 | */ | 140 | */ |
141 | #define SMK_OACCESS "rwxa" | 141 | #define SMK_OACCESS "rwxa" |
142 | #define SMK_ACCESS "rwxat" | 142 | #define SMK_ACCESS "rwxatl" |
143 | #define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1) | 143 | #define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1) |
144 | #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) | 144 | #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) |
145 | #define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN) | 145 | #define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN) |
@@ -282,6 +282,10 @@ static int smk_perm_from_str(const char *string) | |||
282 | case 'T': | 282 | case 'T': |
283 | perm |= MAY_TRANSMUTE; | 283 | perm |= MAY_TRANSMUTE; |
284 | break; | 284 | break; |
285 | case 'l': | ||
286 | case 'L': | ||
287 | perm |= MAY_LOCK; | ||
288 | break; | ||
285 | default: | 289 | default: |
286 | return perm; | 290 | return perm; |
287 | } | 291 | } |
@@ -452,7 +456,7 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, | |||
452 | /* | 456 | /* |
453 | * Minor hack for backward compatibility | 457 | * Minor hack for backward compatibility |
454 | */ | 458 | */ |
455 | if (count != SMK_OLOADLEN && count != SMK_LOADLEN) | 459 | if (count < SMK_OLOADLEN || count > SMK_LOADLEN) |
456 | return -EINVAL; | 460 | return -EINVAL; |
457 | } else { | 461 | } else { |
458 | if (count >= PAGE_SIZE) { | 462 | if (count >= PAGE_SIZE) { |
@@ -592,6 +596,8 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) | |||
592 | seq_putc(s, 'a'); | 596 | seq_putc(s, 'a'); |
593 | if (srp->smk_access & MAY_TRANSMUTE) | 597 | if (srp->smk_access & MAY_TRANSMUTE) |
594 | seq_putc(s, 't'); | 598 | seq_putc(s, 't'); |
599 | if (srp->smk_access & MAY_LOCK) | ||
600 | seq_putc(s, 'l'); | ||
595 | 601 | ||
596 | seq_putc(s, '\n'); | 602 | seq_putc(s, '\n'); |
597 | } | 603 | } |