Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2fd4e669 authored by James Morris's avatar James Morris
Browse files

Merge branch 'smack-for-3.16' of git://git.gitorious.org/smack-next/kernel into next

parents fab71a90 ec554fa7
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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.
+13 −3
Original line number Diff line number Diff line
@@ -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 */
};

/*
@@ -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 */
};

@@ -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
@@ -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);
@@ -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;
+30 −8
Original line number Diff line number Diff line
@@ -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;

@@ -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)
@@ -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
@@ -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);
}

+179 −61
Original line number Diff line number Diff line
@@ -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!
@@ -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);
@@ -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;
}

@@ -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;
}

@@ -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;

@@ -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)
{
@@ -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;
@@ -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
@@ -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;
}

/**
@@ -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
@@ -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;
}

/*
@@ -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;

@@ -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;
@@ -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;
	}

@@ -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)
@@ -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) {
@@ -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;
@@ -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;
@@ -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.
@@ -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;
@@ -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);
}

/**
@@ -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;
	}
@@ -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;
@@ -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;
	}

@@ -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() */
}
@@ -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;

@@ -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;
}
+75 −1
Original line number Diff line number Diff line
@@ -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 */
};

/*
@@ -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
@@ -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",
@@ -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
@@ -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 */
			{""}
	};