Loading Documentation/security/Smack.txt +10 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,16 @@ onlycap these capabilities are effective at for processes with any label. The value is set by writing the desired label to the file or cleared by writing "-" to the file. ptrace This is used to define the current ptrace policy 0 - default: this is the policy that relies on smack access rules. For the PTRACE_READ a subject needs to have a read access on object. For the PTRACE_ATTACH a read-write access is required. 1 - exact: this is the policy that limits PTRACE_ATTACH. Attach is only allowed when subject's and object's labels are equal. PTRACE_READ is not affected. Can be overriden with CAP_SYS_PTRACE. 2 - draconian: this policy behaves like the 'exact' above with an exception that it can't be overriden with CAP_SYS_PTRACE. revoke-subject Writing a Smack label here sets the access to '-' for all access rules with that subject label. Loading security/smack/smack.h +13 −3 Original line number Diff line number Diff line Loading @@ -80,8 +80,8 @@ struct superblock_smack { struct socket_smack { struct smack_known *smk_out; /* outbound label */ char *smk_in; /* inbound label */ char *smk_packet; /* TCP peer label */ struct smack_known *smk_in; /* inbound label */ struct smack_known *smk_packet; /* TCP peer label */ }; /* Loading Loading @@ -133,7 +133,7 @@ struct smk_port_label { struct list_head list; struct sock *smk_sock; /* socket initialized on */ unsigned short smk_port; /* the port number */ char *smk_in; /* incoming label */ struct smack_known *smk_in; /* inbound label */ struct smack_known *smk_out; /* outgoing label */ }; Loading Loading @@ -176,6 +176,14 @@ struct smk_port_label { */ #define SMACK_CIPSO_MAXCATNUM 184 /* 23 * 8 */ /* * Ptrace rules */ #define SMACK_PTRACE_DEFAULT 0 #define SMACK_PTRACE_EXACT 1 #define SMACK_PTRACE_DRACONIAN 2 #define SMACK_PTRACE_MAX SMACK_PTRACE_DRACONIAN /* * Flags for untraditional access modes. * It shouldn't be necessary to avoid conflicts with definitions Loading Loading @@ -225,6 +233,7 @@ struct inode_smack *new_inode_smack(char *); */ int smk_access_entry(char *, char *, struct list_head *); int smk_access(struct smack_known *, char *, int, struct smk_audit_info *); int smk_tskacc(struct task_smack *, char *, u32, struct smk_audit_info *); int smk_curacc(char *, u32, struct smk_audit_info *); struct smack_known *smack_from_secid(const u32); char *smk_parse_smack(const char *string, int len); Loading @@ -244,6 +253,7 @@ extern struct smack_known *smack_net_ambient; extern struct smack_known *smack_onlycap; extern struct smack_known *smack_syslog_label; extern const char *smack_cipso_option; extern int smack_ptrace_rule; extern struct smack_known smack_known_floor; extern struct smack_known smack_known_hat; Loading security/smack/smack_access.c +30 −8 Original line number Diff line number Diff line Loading @@ -192,20 +192,21 @@ int smk_access(struct smack_known *subject_known, char *object_label, } /** * smk_curacc - determine if current has a specific access to an object * smk_tskacc - determine if a task has a specific access to an object * @tsp: a pointer to the subject task * @obj_label: a pointer to the object's Smack label * @mode: the access requested, in "MAY" format * @a : common audit data * * This function checks the current subject label/object label pair * This function checks the subject task's label/object label pair * in the access rule list and returns 0 if the access is permitted, * non zero otherwise. It allows that current may have the capability * non zero otherwise. It allows that the task may have the capability * to override the rules. */ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) int smk_tskacc(struct task_smack *subject, char *obj_label, u32 mode, struct smk_audit_info *a) { struct task_smack *tsp = current_security(); struct smack_known *skp = smk_of_task(tsp); struct smack_known *skp = smk_of_task(subject); int may; int rc; Loading @@ -219,7 +220,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) * it can further restrict access. */ may = smk_access_entry(skp->smk_known, obj_label, &tsp->smk_rules); &subject->smk_rules); if (may < 0) goto out_audit; if ((mode & may) == mode) Loading @@ -241,6 +242,24 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) return rc; } /** * smk_curacc - determine if current has a specific access to an object * @obj_label: a pointer to the object's Smack label * @mode: the access requested, in "MAY" format * @a : common audit data * * This function checks the current subject label/object label pair * in the access rule list and returns 0 if the access is permitted, * non zero otherwise. It allows that current may have the capability * to override the rules. */ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) { struct task_smack *tsp = current_security(); return smk_tskacc(tsp, obj_label, mode, a); } #ifdef CONFIG_AUDIT /** * smack_str_from_perm : helper to transalate an int to a Loading Loading @@ -285,6 +304,9 @@ static void smack_log_callback(struct audit_buffer *ab, void *a) audit_log_untrustedstring(ab, sad->subject); audit_log_format(ab, " object="); audit_log_untrustedstring(ab, sad->object); if (sad->request[0] == '\0') audit_log_format(ab, " labels_differ"); else audit_log_format(ab, " requested=%s", sad->request); } Loading security/smack/smack_lsm.c +179 −61 Original line number Diff line number Diff line Loading @@ -157,6 +157,74 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, return rc; } /** * smk_ptrace_mode - helper function for converting PTRACE_MODE_* into MAY_* * @mode - input mode in form of PTRACE_MODE_* * * Returns a converted MAY_* mode usable by smack rules */ static inline unsigned int smk_ptrace_mode(unsigned int mode) { switch (mode) { case PTRACE_MODE_READ: return MAY_READ; case PTRACE_MODE_ATTACH: return MAY_READWRITE; } return 0; } /** * smk_ptrace_rule_check - helper for ptrace access * @tracer: tracer process * @tracee_label: label of the process that's about to be traced, * the pointer must originate from smack structures * @mode: ptrace attachment mode (PTRACE_MODE_*) * @func: name of the function that called us, used for audit * * Returns 0 on access granted, -error on error */ static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, unsigned int mode, const char *func) { int rc; struct smk_audit_info ad, *saip = NULL; struct task_smack *tsp; struct smack_known *skp; if ((mode & PTRACE_MODE_NOAUDIT) == 0) { smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, tracer); saip = &ad; } tsp = task_security(tracer); skp = smk_of_task(tsp); if ((mode & PTRACE_MODE_ATTACH) && (smack_ptrace_rule == SMACK_PTRACE_EXACT || smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) { if (skp->smk_known == tracee_label) rc = 0; else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) rc = -EACCES; else if (capable(CAP_SYS_PTRACE)) rc = 0; else rc = -EACCES; if (saip) smack_log(skp->smk_known, tracee_label, 0, rc, saip); return rc; } /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ rc = smk_tskacc(tsp, tracee_label, smk_ptrace_mode(mode), saip); return rc; } /* * LSM hooks. * We he, that is fun! Loading @@ -165,16 +233,15 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, /** * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH * @ctp: child task pointer * @mode: ptrace attachment mode * @mode: ptrace attachment mode (PTRACE_MODE_*) * * Returns 0 if access is OK, an error code otherwise * * Do the capability checks, and require read and write. * Do the capability checks. */ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) { int rc; struct smk_audit_info ad; struct smack_known *skp; rc = cap_ptrace_access_check(ctp, mode); Loading @@ -182,10 +249,8 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) return rc; skp = smk_of_task(task_security(ctp)); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, ctp); rc = smk_curacc(skp->smk_known, mode, &ad); rc = smk_ptrace_rule_check(current, skp->smk_known, mode, __func__); return rc; } Loading @@ -195,23 +260,21 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) * * Returns 0 if access is OK, an error code otherwise * * Do the capability checks, and require read and write. * Do the capability checks, and require PTRACE_MODE_ATTACH. */ static int smack_ptrace_traceme(struct task_struct *ptp) { int rc; struct smk_audit_info ad; struct smack_known *skp; rc = cap_ptrace_traceme(ptp); if (rc != 0) return rc; skp = smk_of_task(task_security(ptp)); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, ptp); skp = smk_of_task(current_security()); rc = smk_curacc(skp->smk_known, MAY_READWRITE, &ad); rc = smk_ptrace_rule_check(ptp, skp->smk_known, PTRACE_MODE_ATTACH, __func__); return rc; } Loading Loading @@ -413,9 +476,11 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) * Initialize the root inode. */ isp = inode->i_security; if (inode->i_security == NULL) { inode->i_security = new_inode_smack(sp->smk_root); isp = inode->i_security; if (isp == NULL) { isp = new_inode_smack(sp->smk_root); if (isp == NULL) return -ENOMEM; inode->i_security = isp; } else isp->smk_inode = sp->smk_root; Loading Loading @@ -453,7 +518,7 @@ static int smack_sb_statfs(struct dentry *dentry) * smack_bprm_set_creds - set creds for exec * @bprm: the exec information * * Returns 0 if it gets a blob, -ENOMEM otherwise * Returns 0 if it gets a blob, -EPERM if exec forbidden and -ENOMEM otherwise */ static int smack_bprm_set_creds(struct linux_binprm *bprm) { Loading @@ -473,7 +538,22 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) return 0; if (bprm->unsafe) if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { struct task_struct *tracer; rc = 0; rcu_read_lock(); tracer = ptrace_parent(current); if (likely(tracer != NULL)) rc = smk_ptrace_rule_check(tracer, isp->smk_task->smk_known, PTRACE_MODE_ATTACH, __func__); rcu_read_unlock(); if (rc != 0) return rc; } else if (bprm->unsafe) return -EPERM; bsp->smk_task = isp->smk_task; Loading Loading @@ -880,18 +960,20 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, return; } skp = smk_import_entry(value, size); if (strcmp(name, XATTR_NAME_SMACK) == 0) { skp = smk_import_entry(value, size); if (skp != NULL) isp->smk_inode = skp->smk_known; else isp->smk_inode = smack_known_invalid.smk_known; } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { skp = smk_import_entry(value, size); if (skp != NULL) isp->smk_task = skp; else isp->smk_task = &smack_known_invalid; } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { skp = smk_import_entry(value, size); if (skp != NULL) isp->smk_mmap = skp; else Loading Loading @@ -938,24 +1020,37 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 || strcmp(name, XATTR_NAME_SMACKMMAP)) { strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { if (!smack_privileged(CAP_MAC_ADMIN)) rc = -EPERM; } else rc = cap_inode_removexattr(dentry, name); if (rc != 0) return rc; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); smk_ad_setfield_u_fs_path_dentry(&ad, dentry); if (rc == 0) rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); if (rc != 0) return rc; if (rc == 0) { isp = dentry->d_inode->i_security; /* * Don't do anything special for these. * XATTR_NAME_SMACKIPIN * XATTR_NAME_SMACKIPOUT * XATTR_NAME_SMACKEXEC */ if (strcmp(name, XATTR_NAME_SMACK) == 0) isp->smk_task = NULL; else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) isp->smk_mmap = NULL; } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) isp->smk_flags &= ~SMK_INODE_TRANSMUTE; return rc; return 0; } /** Loading Loading @@ -1000,7 +1095,7 @@ static int smack_inode_getsecurity(const struct inode *inode, ssp = sock->sk->sk_security; if (strcmp(name, XATTR_SMACK_IPIN) == 0) isp = ssp->smk_in; isp = ssp->smk_in->smk_known; else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) isp = ssp->smk_out->smk_known; else Loading Loading @@ -1367,19 +1462,32 @@ static int smack_file_receive(struct file *file) /** * smack_file_open - Smack dentry open processing * @file: the object * @cred: unused * @cred: task credential * * Set the security blob in the file structure. * Allow the open only if the task has read access. There are * many read operations (e.g. fstat) that you can do with an * fd even if you have the file open write-only. * * Returns 0 */ static int smack_file_open(struct file *file, const struct cred *cred) { struct task_smack *tsp = cred->security; struct inode_smack *isp = file_inode(file)->i_security; struct smk_audit_info ad; int rc; if (smack_privileged(CAP_MAC_OVERRIDE)) return 0; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); smk_ad_setfield_u_fs_path(&ad, file->f_path); rc = smk_access(tsp->smk_task, isp->smk_inode, MAY_READ, &ad); if (rc == 0) file->f_security = isp->smk_inode; return 0; return rc; } /* Loading Loading @@ -1764,7 +1872,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) if (ssp == NULL) return -ENOMEM; ssp->smk_in = skp->smk_known; ssp->smk_in = skp; ssp->smk_out = skp; ssp->smk_packet = NULL; Loading Loading @@ -2004,7 +2112,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, if (act == SMK_RECEIVING) { skp = smack_net_ambient; object = ssp->smk_in; object = ssp->smk_in->smk_known; } else { skp = ssp->smk_out; object = smack_net_ambient->smk_known; Loading Loading @@ -2034,9 +2142,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, list_for_each_entry(spp, &smk_ipv6_port_list, list) { if (spp->smk_port != port) continue; object = spp->smk_in; object = spp->smk_in->smk_known; if (act == SMK_CONNECTING) ssp->smk_packet = spp->smk_out->smk_known; ssp->smk_packet = spp->smk_out; break; } Loading Loading @@ -2076,7 +2184,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, int rc = 0; if (value == NULL || size > SMK_LONGLABEL || size == 0) return -EACCES; return -EINVAL; skp = smk_import_entry(value, size); if (skp == NULL) Loading @@ -2100,7 +2208,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, ssp = sock->sk->sk_security; if (strcmp(name, XATTR_SMACK_IPIN) == 0) ssp->smk_in = skp->smk_known; ssp->smk_in = skp; else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { ssp->smk_out = skp; if (sock->sk->sk_family == PF_INET) { Loading Loading @@ -2713,6 +2821,15 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * of the superblock. */ if (opt_dentry->d_parent == opt_dentry) { if (sbp->s_magic == CGROUP_SUPER_MAGIC) { /* * The cgroup filesystem is never mounted, * so there's no opportunity to set the mount * options. */ sbsp->smk_root = smack_known_star.smk_known; sbsp->smk_default = smack_known_star.smk_known; } isp->smk_inode = sbsp->smk_root; isp->smk_flags |= SMK_INODE_INSTANT; goto unlockandout; Loading @@ -2726,16 +2843,20 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) */ switch (sbp->s_magic) { case SMACK_MAGIC: case PIPEFS_MAGIC: case SOCKFS_MAGIC: case CGROUP_SUPER_MAGIC: /* * Casey says that it's a little embarrassing * that the smack file system doesn't do * extended attributes. */ final = smack_known_star.smk_known; break; case PIPEFS_MAGIC: /* * * Casey says pipes are easy (?) * * Socket access is controlled by the socket * structures associated with the task involved. * * Cgroupfs is special */ final = smack_known_star.smk_known; break; Loading @@ -2747,13 +2868,6 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) */ final = ckp->smk_known; break; case SOCKFS_MAGIC: /* * Socket access is controlled by the socket * structures associated with the task involved. */ final = smack_known_star.smk_known; break; case PROC_SUPER_MAGIC: /* * Casey says procfs appears not to care. Loading Loading @@ -2959,30 +3073,34 @@ static int smack_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) { struct smack_known *skp; struct smack_known *okp; struct socket_smack *ssp = sock->sk_security; struct socket_smack *osp = other->sk_security; struct socket_smack *nsp = newsk->sk_security; struct smk_audit_info ad; int rc = 0; #ifdef CONFIG_AUDIT struct lsm_network_audit net; smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); smk_ad_setfield_u_net_sk(&ad, other); #endif if (!smack_privileged(CAP_MAC_OVERRIDE)) { skp = ssp->smk_out; rc = smk_access(skp, osp->smk_in, MAY_WRITE, &ad); okp = osp->smk_out; #ifdef CONFIG_AUDIT smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); smk_ad_setfield_u_net_sk(&ad, other); #endif rc = smk_access(skp, okp->smk_known, MAY_WRITE, &ad); if (rc == 0) rc = smk_access(okp, okp->smk_known, MAY_WRITE, NULL); } /* * Cross reference the peer labels for SO_PEERSEC. */ if (rc == 0) { nsp->smk_packet = ssp->smk_out->smk_known; ssp->smk_packet = osp->smk_out->smk_known; nsp->smk_packet = ssp->smk_out; ssp->smk_packet = osp->smk_out; } return rc; Loading Loading @@ -3014,7 +3132,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) return 0; skp = ssp->smk_out; return smk_access(skp, osp->smk_in, MAY_WRITE, &ad); return smk_access(skp, osp->smk_in->smk_known, MAY_WRITE, &ad); } /** Loading Loading @@ -3109,7 +3227,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap, if (found) return skp; if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) if (ssp != NULL && ssp->smk_in == &smack_known_star) return &smack_known_web; return &smack_known_star; } Loading Loading @@ -3228,7 +3346,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) * This is the simplist possible security model * for networking. */ rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad); if (rc != 0) netlbl_skbuff_err(skb, rc, 0); break; Loading Loading @@ -3263,7 +3381,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock, ssp = sock->sk->sk_security; if (ssp->smk_packet != NULL) { rcp = ssp->smk_packet; rcp = ssp->smk_packet->smk_known; slen = strlen(rcp) + 1; } Loading Loading @@ -3348,7 +3466,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) return; ssp = sk->sk_security; ssp->smk_in = skp->smk_known; ssp->smk_in = skp; ssp->smk_out = skp; /* cssp->smk_packet is already set in smack_inet_csk_clone() */ } Loading Loading @@ -3408,7 +3526,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, * Receiving a packet requires that the other end be able to write * here. Read access is not required. */ rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad); if (rc != 0) return rc; Loading Loading @@ -3452,7 +3570,7 @@ static void smack_inet_csk_clone(struct sock *sk, if (req->peer_secid != 0) { skp = smack_from_secid(req->peer_secid); ssp->smk_packet = skp->smk_known; ssp->smk_packet = skp; } else ssp->smk_packet = NULL; } Loading security/smack/smackfs.c +75 −1 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ enum smk_inos { SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */ SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */ SMK_SYSLOG = 20, /* change syslog label) */ SMK_PTRACE = 21, /* set ptrace rule */ }; /* Loading Loading @@ -100,6 +101,15 @@ struct smack_known *smack_onlycap; */ struct smack_known *smack_syslog_label; /* * Ptrace current rule * SMACK_PTRACE_DEFAULT regular smack ptrace rules (/proc based) * SMACK_PTRACE_EXACT labels must match, but can be overriden with * CAP_SYS_PTRACE * SMACK_PTRACE_DRACONIAN lables must match, CAP_SYS_PTRACE has no effect */ int smack_ptrace_rule = SMACK_PTRACE_DEFAULT; /* * Certain IP addresses may be designated as single label hosts. * Packets are sent there unlabeled, but only from tasks that Loading Loading @@ -1183,7 +1193,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, data[count] = '\0'; rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%d %s", rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%u %s", &host[0], &host[1], &host[2], &host[3], &m, smack); if (rc != 6) { rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s", Loading Loading @@ -2243,6 +2253,68 @@ static const struct file_operations smk_syslog_ops = { }; /** * smk_read_ptrace - read() for /smack/ptrace * @filp: file pointer, not actually used * @buf: where to put the result * @count: maximum to send along * @ppos: where to start * * Returns number of bytes read or error code, as appropriate */ static ssize_t smk_read_ptrace(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { char temp[32]; ssize_t rc; if (*ppos != 0) return 0; sprintf(temp, "%d\n", smack_ptrace_rule); rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); return rc; } /** * smk_write_ptrace - write() for /smack/ptrace * @file: file pointer * @buf: data from user space * @count: bytes sent * @ppos: where to start - must be 0 */ static ssize_t smk_write_ptrace(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char temp[32]; int i; if (!smack_privileged(CAP_MAC_ADMIN)) return -EPERM; if (*ppos != 0 || count >= sizeof(temp) || count == 0) return -EINVAL; if (copy_from_user(temp, buf, count) != 0) return -EFAULT; temp[count] = '\0'; if (sscanf(temp, "%d", &i) != 1) return -EINVAL; if (i < SMACK_PTRACE_DEFAULT || i > SMACK_PTRACE_MAX) return -EINVAL; smack_ptrace_rule = i; return count; } static const struct file_operations smk_ptrace_ops = { .write = smk_write_ptrace, .read = smk_read_ptrace, .llseek = default_llseek, }; /** * smk_fill_super - fill the smackfs superblock * @sb: the empty superblock Loading Loading @@ -2296,6 +2368,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR}, [SMK_SYSLOG] = { "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR}, [SMK_PTRACE] = { "ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR}, /* last one */ {""} }; Loading Loading
Documentation/security/Smack.txt +10 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,16 @@ onlycap these capabilities are effective at for processes with any label. The value is set by writing the desired label to the file or cleared by writing "-" to the file. ptrace This is used to define the current ptrace policy 0 - default: this is the policy that relies on smack access rules. For the PTRACE_READ a subject needs to have a read access on object. For the PTRACE_ATTACH a read-write access is required. 1 - exact: this is the policy that limits PTRACE_ATTACH. Attach is only allowed when subject's and object's labels are equal. PTRACE_READ is not affected. Can be overriden with CAP_SYS_PTRACE. 2 - draconian: this policy behaves like the 'exact' above with an exception that it can't be overriden with CAP_SYS_PTRACE. revoke-subject Writing a Smack label here sets the access to '-' for all access rules with that subject label. Loading
security/smack/smack.h +13 −3 Original line number Diff line number Diff line Loading @@ -80,8 +80,8 @@ struct superblock_smack { struct socket_smack { struct smack_known *smk_out; /* outbound label */ char *smk_in; /* inbound label */ char *smk_packet; /* TCP peer label */ struct smack_known *smk_in; /* inbound label */ struct smack_known *smk_packet; /* TCP peer label */ }; /* Loading Loading @@ -133,7 +133,7 @@ struct smk_port_label { struct list_head list; struct sock *smk_sock; /* socket initialized on */ unsigned short smk_port; /* the port number */ char *smk_in; /* incoming label */ struct smack_known *smk_in; /* inbound label */ struct smack_known *smk_out; /* outgoing label */ }; Loading Loading @@ -176,6 +176,14 @@ struct smk_port_label { */ #define SMACK_CIPSO_MAXCATNUM 184 /* 23 * 8 */ /* * Ptrace rules */ #define SMACK_PTRACE_DEFAULT 0 #define SMACK_PTRACE_EXACT 1 #define SMACK_PTRACE_DRACONIAN 2 #define SMACK_PTRACE_MAX SMACK_PTRACE_DRACONIAN /* * Flags for untraditional access modes. * It shouldn't be necessary to avoid conflicts with definitions Loading Loading @@ -225,6 +233,7 @@ struct inode_smack *new_inode_smack(char *); */ int smk_access_entry(char *, char *, struct list_head *); int smk_access(struct smack_known *, char *, int, struct smk_audit_info *); int smk_tskacc(struct task_smack *, char *, u32, struct smk_audit_info *); int smk_curacc(char *, u32, struct smk_audit_info *); struct smack_known *smack_from_secid(const u32); char *smk_parse_smack(const char *string, int len); Loading @@ -244,6 +253,7 @@ extern struct smack_known *smack_net_ambient; extern struct smack_known *smack_onlycap; extern struct smack_known *smack_syslog_label; extern const char *smack_cipso_option; extern int smack_ptrace_rule; extern struct smack_known smack_known_floor; extern struct smack_known smack_known_hat; Loading
security/smack/smack_access.c +30 −8 Original line number Diff line number Diff line Loading @@ -192,20 +192,21 @@ int smk_access(struct smack_known *subject_known, char *object_label, } /** * smk_curacc - determine if current has a specific access to an object * smk_tskacc - determine if a task has a specific access to an object * @tsp: a pointer to the subject task * @obj_label: a pointer to the object's Smack label * @mode: the access requested, in "MAY" format * @a : common audit data * * This function checks the current subject label/object label pair * This function checks the subject task's label/object label pair * in the access rule list and returns 0 if the access is permitted, * non zero otherwise. It allows that current may have the capability * non zero otherwise. It allows that the task may have the capability * to override the rules. */ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) int smk_tskacc(struct task_smack *subject, char *obj_label, u32 mode, struct smk_audit_info *a) { struct task_smack *tsp = current_security(); struct smack_known *skp = smk_of_task(tsp); struct smack_known *skp = smk_of_task(subject); int may; int rc; Loading @@ -219,7 +220,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) * it can further restrict access. */ may = smk_access_entry(skp->smk_known, obj_label, &tsp->smk_rules); &subject->smk_rules); if (may < 0) goto out_audit; if ((mode & may) == mode) Loading @@ -241,6 +242,24 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) return rc; } /** * smk_curacc - determine if current has a specific access to an object * @obj_label: a pointer to the object's Smack label * @mode: the access requested, in "MAY" format * @a : common audit data * * This function checks the current subject label/object label pair * in the access rule list and returns 0 if the access is permitted, * non zero otherwise. It allows that current may have the capability * to override the rules. */ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) { struct task_smack *tsp = current_security(); return smk_tskacc(tsp, obj_label, mode, a); } #ifdef CONFIG_AUDIT /** * smack_str_from_perm : helper to transalate an int to a Loading Loading @@ -285,6 +304,9 @@ static void smack_log_callback(struct audit_buffer *ab, void *a) audit_log_untrustedstring(ab, sad->subject); audit_log_format(ab, " object="); audit_log_untrustedstring(ab, sad->object); if (sad->request[0] == '\0') audit_log_format(ab, " labels_differ"); else audit_log_format(ab, " requested=%s", sad->request); } Loading
security/smack/smack_lsm.c +179 −61 Original line number Diff line number Diff line Loading @@ -157,6 +157,74 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, return rc; } /** * smk_ptrace_mode - helper function for converting PTRACE_MODE_* into MAY_* * @mode - input mode in form of PTRACE_MODE_* * * Returns a converted MAY_* mode usable by smack rules */ static inline unsigned int smk_ptrace_mode(unsigned int mode) { switch (mode) { case PTRACE_MODE_READ: return MAY_READ; case PTRACE_MODE_ATTACH: return MAY_READWRITE; } return 0; } /** * smk_ptrace_rule_check - helper for ptrace access * @tracer: tracer process * @tracee_label: label of the process that's about to be traced, * the pointer must originate from smack structures * @mode: ptrace attachment mode (PTRACE_MODE_*) * @func: name of the function that called us, used for audit * * Returns 0 on access granted, -error on error */ static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, unsigned int mode, const char *func) { int rc; struct smk_audit_info ad, *saip = NULL; struct task_smack *tsp; struct smack_known *skp; if ((mode & PTRACE_MODE_NOAUDIT) == 0) { smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, tracer); saip = &ad; } tsp = task_security(tracer); skp = smk_of_task(tsp); if ((mode & PTRACE_MODE_ATTACH) && (smack_ptrace_rule == SMACK_PTRACE_EXACT || smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) { if (skp->smk_known == tracee_label) rc = 0; else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) rc = -EACCES; else if (capable(CAP_SYS_PTRACE)) rc = 0; else rc = -EACCES; if (saip) smack_log(skp->smk_known, tracee_label, 0, rc, saip); return rc; } /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ rc = smk_tskacc(tsp, tracee_label, smk_ptrace_mode(mode), saip); return rc; } /* * LSM hooks. * We he, that is fun! Loading @@ -165,16 +233,15 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, /** * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH * @ctp: child task pointer * @mode: ptrace attachment mode * @mode: ptrace attachment mode (PTRACE_MODE_*) * * Returns 0 if access is OK, an error code otherwise * * Do the capability checks, and require read and write. * Do the capability checks. */ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) { int rc; struct smk_audit_info ad; struct smack_known *skp; rc = cap_ptrace_access_check(ctp, mode); Loading @@ -182,10 +249,8 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) return rc; skp = smk_of_task(task_security(ctp)); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, ctp); rc = smk_curacc(skp->smk_known, mode, &ad); rc = smk_ptrace_rule_check(current, skp->smk_known, mode, __func__); return rc; } Loading @@ -195,23 +260,21 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) * * Returns 0 if access is OK, an error code otherwise * * Do the capability checks, and require read and write. * Do the capability checks, and require PTRACE_MODE_ATTACH. */ static int smack_ptrace_traceme(struct task_struct *ptp) { int rc; struct smk_audit_info ad; struct smack_known *skp; rc = cap_ptrace_traceme(ptp); if (rc != 0) return rc; skp = smk_of_task(task_security(ptp)); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, ptp); skp = smk_of_task(current_security()); rc = smk_curacc(skp->smk_known, MAY_READWRITE, &ad); rc = smk_ptrace_rule_check(ptp, skp->smk_known, PTRACE_MODE_ATTACH, __func__); return rc; } Loading Loading @@ -413,9 +476,11 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) * Initialize the root inode. */ isp = inode->i_security; if (inode->i_security == NULL) { inode->i_security = new_inode_smack(sp->smk_root); isp = inode->i_security; if (isp == NULL) { isp = new_inode_smack(sp->smk_root); if (isp == NULL) return -ENOMEM; inode->i_security = isp; } else isp->smk_inode = sp->smk_root; Loading Loading @@ -453,7 +518,7 @@ static int smack_sb_statfs(struct dentry *dentry) * smack_bprm_set_creds - set creds for exec * @bprm: the exec information * * Returns 0 if it gets a blob, -ENOMEM otherwise * Returns 0 if it gets a blob, -EPERM if exec forbidden and -ENOMEM otherwise */ static int smack_bprm_set_creds(struct linux_binprm *bprm) { Loading @@ -473,7 +538,22 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) return 0; if (bprm->unsafe) if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { struct task_struct *tracer; rc = 0; rcu_read_lock(); tracer = ptrace_parent(current); if (likely(tracer != NULL)) rc = smk_ptrace_rule_check(tracer, isp->smk_task->smk_known, PTRACE_MODE_ATTACH, __func__); rcu_read_unlock(); if (rc != 0) return rc; } else if (bprm->unsafe) return -EPERM; bsp->smk_task = isp->smk_task; Loading Loading @@ -880,18 +960,20 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, return; } skp = smk_import_entry(value, size); if (strcmp(name, XATTR_NAME_SMACK) == 0) { skp = smk_import_entry(value, size); if (skp != NULL) isp->smk_inode = skp->smk_known; else isp->smk_inode = smack_known_invalid.smk_known; } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { skp = smk_import_entry(value, size); if (skp != NULL) isp->smk_task = skp; else isp->smk_task = &smack_known_invalid; } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { skp = smk_import_entry(value, size); if (skp != NULL) isp->smk_mmap = skp; else Loading Loading @@ -938,24 +1020,37 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 || strcmp(name, XATTR_NAME_SMACKMMAP)) { strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { if (!smack_privileged(CAP_MAC_ADMIN)) rc = -EPERM; } else rc = cap_inode_removexattr(dentry, name); if (rc != 0) return rc; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); smk_ad_setfield_u_fs_path_dentry(&ad, dentry); if (rc == 0) rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); if (rc != 0) return rc; if (rc == 0) { isp = dentry->d_inode->i_security; /* * Don't do anything special for these. * XATTR_NAME_SMACKIPIN * XATTR_NAME_SMACKIPOUT * XATTR_NAME_SMACKEXEC */ if (strcmp(name, XATTR_NAME_SMACK) == 0) isp->smk_task = NULL; else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) isp->smk_mmap = NULL; } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) isp->smk_flags &= ~SMK_INODE_TRANSMUTE; return rc; return 0; } /** Loading Loading @@ -1000,7 +1095,7 @@ static int smack_inode_getsecurity(const struct inode *inode, ssp = sock->sk->sk_security; if (strcmp(name, XATTR_SMACK_IPIN) == 0) isp = ssp->smk_in; isp = ssp->smk_in->smk_known; else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) isp = ssp->smk_out->smk_known; else Loading Loading @@ -1367,19 +1462,32 @@ static int smack_file_receive(struct file *file) /** * smack_file_open - Smack dentry open processing * @file: the object * @cred: unused * @cred: task credential * * Set the security blob in the file structure. * Allow the open only if the task has read access. There are * many read operations (e.g. fstat) that you can do with an * fd even if you have the file open write-only. * * Returns 0 */ static int smack_file_open(struct file *file, const struct cred *cred) { struct task_smack *tsp = cred->security; struct inode_smack *isp = file_inode(file)->i_security; struct smk_audit_info ad; int rc; if (smack_privileged(CAP_MAC_OVERRIDE)) return 0; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); smk_ad_setfield_u_fs_path(&ad, file->f_path); rc = smk_access(tsp->smk_task, isp->smk_inode, MAY_READ, &ad); if (rc == 0) file->f_security = isp->smk_inode; return 0; return rc; } /* Loading Loading @@ -1764,7 +1872,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) if (ssp == NULL) return -ENOMEM; ssp->smk_in = skp->smk_known; ssp->smk_in = skp; ssp->smk_out = skp; ssp->smk_packet = NULL; Loading Loading @@ -2004,7 +2112,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, if (act == SMK_RECEIVING) { skp = smack_net_ambient; object = ssp->smk_in; object = ssp->smk_in->smk_known; } else { skp = ssp->smk_out; object = smack_net_ambient->smk_known; Loading Loading @@ -2034,9 +2142,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, list_for_each_entry(spp, &smk_ipv6_port_list, list) { if (spp->smk_port != port) continue; object = spp->smk_in; object = spp->smk_in->smk_known; if (act == SMK_CONNECTING) ssp->smk_packet = spp->smk_out->smk_known; ssp->smk_packet = spp->smk_out; break; } Loading Loading @@ -2076,7 +2184,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, int rc = 0; if (value == NULL || size > SMK_LONGLABEL || size == 0) return -EACCES; return -EINVAL; skp = smk_import_entry(value, size); if (skp == NULL) Loading @@ -2100,7 +2208,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, ssp = sock->sk->sk_security; if (strcmp(name, XATTR_SMACK_IPIN) == 0) ssp->smk_in = skp->smk_known; ssp->smk_in = skp; else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { ssp->smk_out = skp; if (sock->sk->sk_family == PF_INET) { Loading Loading @@ -2713,6 +2821,15 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * of the superblock. */ if (opt_dentry->d_parent == opt_dentry) { if (sbp->s_magic == CGROUP_SUPER_MAGIC) { /* * The cgroup filesystem is never mounted, * so there's no opportunity to set the mount * options. */ sbsp->smk_root = smack_known_star.smk_known; sbsp->smk_default = smack_known_star.smk_known; } isp->smk_inode = sbsp->smk_root; isp->smk_flags |= SMK_INODE_INSTANT; goto unlockandout; Loading @@ -2726,16 +2843,20 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) */ switch (sbp->s_magic) { case SMACK_MAGIC: case PIPEFS_MAGIC: case SOCKFS_MAGIC: case CGROUP_SUPER_MAGIC: /* * Casey says that it's a little embarrassing * that the smack file system doesn't do * extended attributes. */ final = smack_known_star.smk_known; break; case PIPEFS_MAGIC: /* * * Casey says pipes are easy (?) * * Socket access is controlled by the socket * structures associated with the task involved. * * Cgroupfs is special */ final = smack_known_star.smk_known; break; Loading @@ -2747,13 +2868,6 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) */ final = ckp->smk_known; break; case SOCKFS_MAGIC: /* * Socket access is controlled by the socket * structures associated with the task involved. */ final = smack_known_star.smk_known; break; case PROC_SUPER_MAGIC: /* * Casey says procfs appears not to care. Loading Loading @@ -2959,30 +3073,34 @@ static int smack_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) { struct smack_known *skp; struct smack_known *okp; struct socket_smack *ssp = sock->sk_security; struct socket_smack *osp = other->sk_security; struct socket_smack *nsp = newsk->sk_security; struct smk_audit_info ad; int rc = 0; #ifdef CONFIG_AUDIT struct lsm_network_audit net; smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); smk_ad_setfield_u_net_sk(&ad, other); #endif if (!smack_privileged(CAP_MAC_OVERRIDE)) { skp = ssp->smk_out; rc = smk_access(skp, osp->smk_in, MAY_WRITE, &ad); okp = osp->smk_out; #ifdef CONFIG_AUDIT smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); smk_ad_setfield_u_net_sk(&ad, other); #endif rc = smk_access(skp, okp->smk_known, MAY_WRITE, &ad); if (rc == 0) rc = smk_access(okp, okp->smk_known, MAY_WRITE, NULL); } /* * Cross reference the peer labels for SO_PEERSEC. */ if (rc == 0) { nsp->smk_packet = ssp->smk_out->smk_known; ssp->smk_packet = osp->smk_out->smk_known; nsp->smk_packet = ssp->smk_out; ssp->smk_packet = osp->smk_out; } return rc; Loading Loading @@ -3014,7 +3132,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) return 0; skp = ssp->smk_out; return smk_access(skp, osp->smk_in, MAY_WRITE, &ad); return smk_access(skp, osp->smk_in->smk_known, MAY_WRITE, &ad); } /** Loading Loading @@ -3109,7 +3227,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap, if (found) return skp; if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) if (ssp != NULL && ssp->smk_in == &smack_known_star) return &smack_known_web; return &smack_known_star; } Loading Loading @@ -3228,7 +3346,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) * This is the simplist possible security model * for networking. */ rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad); if (rc != 0) netlbl_skbuff_err(skb, rc, 0); break; Loading Loading @@ -3263,7 +3381,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock, ssp = sock->sk->sk_security; if (ssp->smk_packet != NULL) { rcp = ssp->smk_packet; rcp = ssp->smk_packet->smk_known; slen = strlen(rcp) + 1; } Loading Loading @@ -3348,7 +3466,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) return; ssp = sk->sk_security; ssp->smk_in = skp->smk_known; ssp->smk_in = skp; ssp->smk_out = skp; /* cssp->smk_packet is already set in smack_inet_csk_clone() */ } Loading Loading @@ -3408,7 +3526,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, * Receiving a packet requires that the other end be able to write * here. Read access is not required. */ rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad); if (rc != 0) return rc; Loading Loading @@ -3452,7 +3570,7 @@ static void smack_inet_csk_clone(struct sock *sk, if (req->peer_secid != 0) { skp = smack_from_secid(req->peer_secid); ssp->smk_packet = skp->smk_known; ssp->smk_packet = skp; } else ssp->smk_packet = NULL; } Loading
security/smack/smackfs.c +75 −1 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ enum smk_inos { SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */ SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */ SMK_SYSLOG = 20, /* change syslog label) */ SMK_PTRACE = 21, /* set ptrace rule */ }; /* Loading Loading @@ -100,6 +101,15 @@ struct smack_known *smack_onlycap; */ struct smack_known *smack_syslog_label; /* * Ptrace current rule * SMACK_PTRACE_DEFAULT regular smack ptrace rules (/proc based) * SMACK_PTRACE_EXACT labels must match, but can be overriden with * CAP_SYS_PTRACE * SMACK_PTRACE_DRACONIAN lables must match, CAP_SYS_PTRACE has no effect */ int smack_ptrace_rule = SMACK_PTRACE_DEFAULT; /* * Certain IP addresses may be designated as single label hosts. * Packets are sent there unlabeled, but only from tasks that Loading Loading @@ -1183,7 +1193,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, data[count] = '\0'; rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%d %s", rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%u %s", &host[0], &host[1], &host[2], &host[3], &m, smack); if (rc != 6) { rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s", Loading Loading @@ -2243,6 +2253,68 @@ static const struct file_operations smk_syslog_ops = { }; /** * smk_read_ptrace - read() for /smack/ptrace * @filp: file pointer, not actually used * @buf: where to put the result * @count: maximum to send along * @ppos: where to start * * Returns number of bytes read or error code, as appropriate */ static ssize_t smk_read_ptrace(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { char temp[32]; ssize_t rc; if (*ppos != 0) return 0; sprintf(temp, "%d\n", smack_ptrace_rule); rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); return rc; } /** * smk_write_ptrace - write() for /smack/ptrace * @file: file pointer * @buf: data from user space * @count: bytes sent * @ppos: where to start - must be 0 */ static ssize_t smk_write_ptrace(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char temp[32]; int i; if (!smack_privileged(CAP_MAC_ADMIN)) return -EPERM; if (*ppos != 0 || count >= sizeof(temp) || count == 0) return -EINVAL; if (copy_from_user(temp, buf, count) != 0) return -EFAULT; temp[count] = '\0'; if (sscanf(temp, "%d", &i) != 1) return -EINVAL; if (i < SMACK_PTRACE_DEFAULT || i > SMACK_PTRACE_MAX) return -EINVAL; smack_ptrace_rule = i; return count; } static const struct file_operations smk_ptrace_ops = { .write = smk_write_ptrace, .read = smk_read_ptrace, .llseek = default_llseek, }; /** * smk_fill_super - fill the smackfs superblock * @sb: the empty superblock Loading Loading @@ -2296,6 +2368,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR}, [SMK_SYSLOG] = { "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR}, [SMK_PTRACE] = { "ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR}, /* last one */ {""} }; Loading