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 | |
| 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')
| -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 | |
