diff options
author | Lukasz Pawelczyk <l.pawelczyk@partner.samsung.com> | 2014-03-11 12:07:06 -0400 |
---|---|---|
committer | Casey Schaufler <casey@schaufler-ca.com> | 2014-04-11 17:34:35 -0400 |
commit | 668678185247303450e60df14569f94cf5775fea (patch) | |
tree | 2f2b77d7a2769745699e48685c9dbf26d8dd0c98 /security/smack | |
parent | 5663884caab166f87ab8c68ec7c62b1cce85a400 (diff) |
Smack: adds smackfs/ptrace interface
This allows to limit ptrace beyond the regular smack access rules.
It adds a smackfs/ptrace interface that allows smack to be configured
to require equal smack labels for PTRACE_MODE_ATTACH access.
See the changes in Documentation/security/Smack.txt below for details.
Signed-off-by: Lukasz Pawelczyk <l.pawelczyk@partner.samsung.com>
Signed-off-by: Rafal Krypa <r.krypa@samsung.com>
Diffstat (limited to 'security/smack')
-rw-r--r-- | security/smack/smack.h | 9 | ||||
-rw-r--r-- | security/smack/smack_access.c | 5 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 22 | ||||
-rw-r--r-- | security/smack/smackfs.c | 74 |
4 files changed, 108 insertions, 2 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h index b9dfc4e1d3e0..fade085b1128 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -177,6 +177,14 @@ 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 | * Ptrace rules | ||
181 | */ | ||
182 | #define SMACK_PTRACE_DEFAULT 0 | ||
183 | #define SMACK_PTRACE_EXACT 1 | ||
184 | #define SMACK_PTRACE_DRACONIAN 2 | ||
185 | #define SMACK_PTRACE_MAX SMACK_PTRACE_DRACONIAN | ||
186 | |||
187 | /* | ||
180 | * Flags for untraditional access modes. | 188 | * Flags for untraditional access modes. |
181 | * It shouldn't be necessary to avoid conflicts with definitions | 189 | * It shouldn't be necessary to avoid conflicts with definitions |
182 | * in fs.h, but do so anyway. | 190 | * in fs.h, but do so anyway. |
@@ -245,6 +253,7 @@ extern struct smack_known *smack_net_ambient; | |||
245 | extern struct smack_known *smack_onlycap; | 253 | extern struct smack_known *smack_onlycap; |
246 | extern struct smack_known *smack_syslog_label; | 254 | extern struct smack_known *smack_syslog_label; |
247 | extern const char *smack_cipso_option; | 255 | extern const char *smack_cipso_option; |
256 | extern int smack_ptrace_rule; | ||
248 | 257 | ||
249 | extern struct smack_known smack_known_floor; | 258 | extern struct smack_known smack_known_floor; |
250 | extern struct smack_known smack_known_hat; | 259 | extern struct smack_known smack_known_hat; |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index f161debed02b..c062e9467b62 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -304,7 +304,10 @@ static void smack_log_callback(struct audit_buffer *ab, void *a) | |||
304 | audit_log_untrustedstring(ab, sad->subject); | 304 | audit_log_untrustedstring(ab, sad->subject); |
305 | audit_log_format(ab, " object="); | 305 | audit_log_format(ab, " object="); |
306 | audit_log_untrustedstring(ab, sad->object); | 306 | audit_log_untrustedstring(ab, sad->object); |
307 | audit_log_format(ab, " requested=%s", sad->request); | 307 | if (sad->request[0] == '\0') |
308 | audit_log_format(ab, " labels_differ"); | ||
309 | else | ||
310 | audit_log_format(ab, " requested=%s", sad->request); | ||
308 | } | 311 | } |
309 | 312 | ||
310 | /** | 313 | /** |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 4d6f37644baa..787dcf12f15c 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -178,7 +178,8 @@ static inline unsigned int smk_ptrace_mode(unsigned int mode) | |||
178 | /** | 178 | /** |
179 | * smk_ptrace_rule_check - helper for ptrace access | 179 | * smk_ptrace_rule_check - helper for ptrace access |
180 | * @tracer: tracer process | 180 | * @tracer: tracer process |
181 | * @tracee_label: label of the process that's about to be traced | 181 | * @tracee_label: label of the process that's about to be traced, |
182 | * the pointer must originate from smack structures | ||
182 | * @mode: ptrace attachment mode (PTRACE_MODE_*) | 183 | * @mode: ptrace attachment mode (PTRACE_MODE_*) |
183 | * @func: name of the function that called us, used for audit | 184 | * @func: name of the function that called us, used for audit |
184 | * | 185 | * |
@@ -201,6 +202,25 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, | |||
201 | tsp = task_security(tracer); | 202 | tsp = task_security(tracer); |
202 | skp = smk_of_task(tsp); | 203 | skp = smk_of_task(tsp); |
203 | 204 | ||
205 | if ((mode & PTRACE_MODE_ATTACH) && | ||
206 | (smack_ptrace_rule == SMACK_PTRACE_EXACT || | ||
207 | smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) { | ||
208 | if (skp->smk_known == tracee_label) | ||
209 | rc = 0; | ||
210 | else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) | ||
211 | rc = -EACCES; | ||
212 | else if (capable(CAP_SYS_PTRACE)) | ||
213 | rc = 0; | ||
214 | else | ||
215 | rc = -EACCES; | ||
216 | |||
217 | if (saip) | ||
218 | smack_log(skp->smk_known, tracee_label, 0, rc, saip); | ||
219 | |||
220 | return rc; | ||
221 | } | ||
222 | |||
223 | /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ | ||
204 | rc = smk_tskacc(tsp, tracee_label, smk_ptrace_mode(mode), saip); | 224 | rc = smk_tskacc(tsp, tracee_label, smk_ptrace_mode(mode), saip); |
205 | return rc; | 225 | return rc; |
206 | } | 226 | } |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 3198cfe1dcc6..177d87875394 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -53,6 +53,7 @@ enum smk_inos { | |||
53 | SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */ | 53 | SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */ |
54 | SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */ | 54 | SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */ |
55 | SMK_SYSLOG = 20, /* change syslog label) */ | 55 | SMK_SYSLOG = 20, /* change syslog label) */ |
56 | SMK_PTRACE = 21, /* set ptrace rule */ | ||
56 | }; | 57 | }; |
57 | 58 | ||
58 | /* | 59 | /* |
@@ -101,6 +102,15 @@ struct smack_known *smack_onlycap; | |||
101 | struct smack_known *smack_syslog_label; | 102 | struct smack_known *smack_syslog_label; |
102 | 103 | ||
103 | /* | 104 | /* |
105 | * Ptrace current rule | ||
106 | * SMACK_PTRACE_DEFAULT regular smack ptrace rules (/proc based) | ||
107 | * SMACK_PTRACE_EXACT labels must match, but can be overriden with | ||
108 | * CAP_SYS_PTRACE | ||
109 | * SMACK_PTRACE_DRACONIAN lables must match, CAP_SYS_PTRACE has no effect | ||
110 | */ | ||
111 | int smack_ptrace_rule = SMACK_PTRACE_DEFAULT; | ||
112 | |||
113 | /* | ||
104 | * Certain IP addresses may be designated as single label hosts. | 114 | * Certain IP addresses may be designated as single label hosts. |
105 | * Packets are sent there unlabeled, but only from tasks that | 115 | * Packets are sent there unlabeled, but only from tasks that |
106 | * can write to the specified label. | 116 | * can write to the specified label. |
@@ -2244,6 +2254,68 @@ static const struct file_operations smk_syslog_ops = { | |||
2244 | 2254 | ||
2245 | 2255 | ||
2246 | /** | 2256 | /** |
2257 | * smk_read_ptrace - read() for /smack/ptrace | ||
2258 | * @filp: file pointer, not actually used | ||
2259 | * @buf: where to put the result | ||
2260 | * @count: maximum to send along | ||
2261 | * @ppos: where to start | ||
2262 | * | ||
2263 | * Returns number of bytes read or error code, as appropriate | ||
2264 | */ | ||
2265 | static ssize_t smk_read_ptrace(struct file *filp, char __user *buf, | ||
2266 | size_t count, loff_t *ppos) | ||
2267 | { | ||
2268 | char temp[32]; | ||
2269 | ssize_t rc; | ||
2270 | |||
2271 | if (*ppos != 0) | ||
2272 | return 0; | ||
2273 | |||
2274 | sprintf(temp, "%d\n", smack_ptrace_rule); | ||
2275 | rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); | ||
2276 | return rc; | ||
2277 | } | ||
2278 | |||
2279 | /** | ||
2280 | * smk_write_ptrace - write() for /smack/ptrace | ||
2281 | * @file: file pointer | ||
2282 | * @buf: data from user space | ||
2283 | * @count: bytes sent | ||
2284 | * @ppos: where to start - must be 0 | ||
2285 | */ | ||
2286 | static ssize_t smk_write_ptrace(struct file *file, const char __user *buf, | ||
2287 | size_t count, loff_t *ppos) | ||
2288 | { | ||
2289 | char temp[32]; | ||
2290 | int i; | ||
2291 | |||
2292 | if (!smack_privileged(CAP_MAC_ADMIN)) | ||
2293 | return -EPERM; | ||
2294 | |||
2295 | if (*ppos != 0 || count >= sizeof(temp) || count == 0) | ||
2296 | return -EINVAL; | ||
2297 | |||
2298 | if (copy_from_user(temp, buf, count) != 0) | ||
2299 | return -EFAULT; | ||
2300 | |||
2301 | temp[count] = '\0'; | ||
2302 | |||
2303 | if (sscanf(temp, "%d", &i) != 1) | ||
2304 | return -EINVAL; | ||
2305 | if (i < SMACK_PTRACE_DEFAULT || i > SMACK_PTRACE_MAX) | ||
2306 | return -EINVAL; | ||
2307 | smack_ptrace_rule = i; | ||
2308 | |||
2309 | return count; | ||
2310 | } | ||
2311 | |||
2312 | static const struct file_operations smk_ptrace_ops = { | ||
2313 | .write = smk_write_ptrace, | ||
2314 | .read = smk_read_ptrace, | ||
2315 | .llseek = default_llseek, | ||
2316 | }; | ||
2317 | |||
2318 | /** | ||
2247 | * smk_fill_super - fill the smackfs superblock | 2319 | * smk_fill_super - fill the smackfs superblock |
2248 | * @sb: the empty superblock | 2320 | * @sb: the empty superblock |
2249 | * @data: unused | 2321 | * @data: unused |
@@ -2296,6 +2368,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
2296 | "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR}, | 2368 | "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR}, |
2297 | [SMK_SYSLOG] = { | 2369 | [SMK_SYSLOG] = { |
2298 | "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR}, | 2370 | "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR}, |
2371 | [SMK_PTRACE] = { | ||
2372 | "ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR}, | ||
2299 | /* last one */ | 2373 | /* last one */ |
2300 | {""} | 2374 | {""} |
2301 | }; | 2375 | }; |