|
@@ -516,6 +516,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
|
|
|
const struct qstr *qstr, char **name,
|
|
|
void **value, size_t *len)
|
|
|
{
|
|
|
+ struct smack_known *skp;
|
|
|
+ char *csp = smk_of_current();
|
|
|
char *isp = smk_of_inode(inode);
|
|
|
char *dsp = smk_of_inode(dir);
|
|
|
int may;
|
|
@@ -527,8 +529,9 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
|
|
|
}
|
|
|
|
|
|
if (value) {
|
|
|
+ skp = smk_find_entry(csp);
|
|
|
rcu_read_lock();
|
|
|
- may = smk_access_entry(smk_of_current(), dsp, &smack_rule_list);
|
|
|
+ may = smk_access_entry(csp, dsp, &skp->smk_rules);
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
/*
|
|
@@ -1138,6 +1141,7 @@ static int smack_file_mmap(struct file *file,
|
|
|
unsigned long flags, unsigned long addr,
|
|
|
unsigned long addr_only)
|
|
|
{
|
|
|
+ struct smack_known *skp;
|
|
|
struct smack_rule *srp;
|
|
|
struct task_smack *tsp;
|
|
|
char *sp;
|
|
@@ -1170,6 +1174,7 @@ static int smack_file_mmap(struct file *file,
|
|
|
|
|
|
tsp = current_security();
|
|
|
sp = smk_of_current();
|
|
|
+ skp = smk_find_entry(sp);
|
|
|
rc = 0;
|
|
|
|
|
|
rcu_read_lock();
|
|
@@ -1177,15 +1182,8 @@ static int smack_file_mmap(struct file *file,
|
|
|
* For each Smack rule associated with the subject
|
|
|
* label verify that the SMACK64MMAP also has access
|
|
|
* to that rule's object label.
|
|
|
- *
|
|
|
- * Because neither of the labels comes
|
|
|
- * from the networking code it is sufficient
|
|
|
- * to compare pointers.
|
|
|
*/
|
|
|
- list_for_each_entry_rcu(srp, &smack_rule_list, list) {
|
|
|
- if (srp->smk_subject != sp)
|
|
|
- continue;
|
|
|
-
|
|
|
+ list_for_each_entry_rcu(srp, &skp->smk_rules, list) {
|
|
|
osmack = srp->smk_object;
|
|
|
/*
|
|
|
* Matching labels always allows access.
|
|
@@ -1214,7 +1212,8 @@ static int smack_file_mmap(struct file *file,
|
|
|
* If there isn't one a SMACK64MMAP subject
|
|
|
* can't have as much access as current.
|
|
|
*/
|
|
|
- mmay = smk_access_entry(msmack, osmack, &smack_rule_list);
|
|
|
+ skp = smk_find_entry(msmack);
|
|
|
+ mmay = smk_access_entry(msmack, osmack, &skp->smk_rules);
|
|
|
if (mmay == -ENOENT) {
|
|
|
rc = -EACCES;
|
|
|
break;
|
|
@@ -1711,7 +1710,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
|
|
|
|
|
|
ssp->smk_in = csp;
|
|
|
ssp->smk_out = csp;
|
|
|
- ssp->smk_packet[0] = '\0';
|
|
|
+ ssp->smk_packet = NULL;
|
|
|
|
|
|
sk->sk_security = ssp;
|
|
|
|
|
@@ -2813,16 +2812,17 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
|
|
|
return smack_netlabel_send(sock->sk, sip);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat pair to smack
|
|
|
* @sap: netlabel secattr
|
|
|
- * @sip: where to put the result
|
|
|
+ * @ssp: socket security information
|
|
|
*
|
|
|
- * Copies a smack label into sip
|
|
|
+ * Returns a pointer to a Smack label found on the label list.
|
|
|
*/
|
|
|
-static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip)
|
|
|
+static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
|
|
|
+ struct socket_smack *ssp)
|
|
|
{
|
|
|
+ struct smack_known *skp;
|
|
|
char smack[SMK_LABELLEN];
|
|
|
char *sp;
|
|
|
int pcat;
|
|
@@ -2852,15 +2852,43 @@ static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip)
|
|
|
* we are already done. WeeHee.
|
|
|
*/
|
|
|
if (sap->attr.mls.lvl == smack_cipso_direct) {
|
|
|
- memcpy(sip, smack, SMK_MAXLEN);
|
|
|
- return;
|
|
|
+ /*
|
|
|
+ * The label sent is usually on the label list.
|
|
|
+ *
|
|
|
+ * If it is not we may still want to allow the
|
|
|
+ * delivery.
|
|
|
+ *
|
|
|
+ * If the recipient is accepting all packets
|
|
|
+ * because it is using the star ("*") label
|
|
|
+ * for SMACK64IPIN provide the web ("@") label
|
|
|
+ * so that a directed response will succeed.
|
|
|
+ * This is not very correct from a MAC point
|
|
|
+ * of view, but gets around the problem that
|
|
|
+ * locking prevents adding the newly discovered
|
|
|
+ * label to the list.
|
|
|
+ * The case where the recipient is not using
|
|
|
+ * the star label should obviously fail.
|
|
|
+ * The easy way to do this is to provide the
|
|
|
+ * star label as the subject label.
|
|
|
+ */
|
|
|
+ skp = smk_find_entry(smack);
|
|
|
+ if (skp != NULL)
|
|
|
+ return skp->smk_known;
|
|
|
+ if (ssp != NULL &&
|
|
|
+ ssp->smk_in == smack_known_star.smk_known)
|
|
|
+ return smack_known_web.smk_known;
|
|
|
+ return smack_known_star.smk_known;
|
|
|
}
|
|
|
/*
|
|
|
* Look it up in the supplied table if it is not
|
|
|
* a direct mapping.
|
|
|
*/
|
|
|
- smack_from_cipso(sap->attr.mls.lvl, smack, sip);
|
|
|
- return;
|
|
|
+ sp = smack_from_cipso(sap->attr.mls.lvl, smack);
|
|
|
+ if (sp != NULL)
|
|
|
+ return sp;
|
|
|
+ if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
|
|
|
+ return smack_known_web.smk_known;
|
|
|
+ return smack_known_star.smk_known;
|
|
|
}
|
|
|
if ((sap->flags & NETLBL_SECATTR_SECID) != 0) {
|
|
|
/*
|
|
@@ -2875,16 +2903,14 @@ static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip)
|
|
|
* secid is from a fallback.
|
|
|
*/
|
|
|
BUG_ON(sp == NULL);
|
|
|
- strncpy(sip, sp, SMK_MAXLEN);
|
|
|
- return;
|
|
|
+ return sp;
|
|
|
}
|
|
|
/*
|
|
|
* Without guidance regarding the smack value
|
|
|
* for the packet fall back on the network
|
|
|
* ambient value.
|
|
|
*/
|
|
|
- strncpy(sip, smack_net_ambient, SMK_MAXLEN);
|
|
|
- return;
|
|
|
+ return smack_net_ambient;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -2898,7 +2924,6 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|
|
{
|
|
|
struct netlbl_lsm_secattr secattr;
|
|
|
struct socket_smack *ssp = sk->sk_security;
|
|
|
- char smack[SMK_LABELLEN];
|
|
|
char *csp;
|
|
|
int rc;
|
|
|
struct smk_audit_info ad;
|
|
@@ -2911,10 +2936,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|
|
netlbl_secattr_init(&secattr);
|
|
|
|
|
|
rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr);
|
|
|
- if (rc == 0) {
|
|
|
- smack_from_secattr(&secattr, smack);
|
|
|
- csp = smack;
|
|
|
- } else
|
|
|
+ if (rc == 0)
|
|
|
+ csp = smack_from_secattr(&secattr, ssp);
|
|
|
+ else
|
|
|
csp = smack_net_ambient;
|
|
|
|
|
|
netlbl_secattr_destroy(&secattr);
|
|
@@ -2951,15 +2975,19 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
|
|
|
int __user *optlen, unsigned len)
|
|
|
{
|
|
|
struct socket_smack *ssp;
|
|
|
- int slen;
|
|
|
+ char *rcp = "";
|
|
|
+ int slen = 1;
|
|
|
int rc = 0;
|
|
|
|
|
|
ssp = sock->sk->sk_security;
|
|
|
- slen = strlen(ssp->smk_packet) + 1;
|
|
|
+ if (ssp->smk_packet != NULL) {
|
|
|
+ rcp = ssp->smk_packet;
|
|
|
+ slen = strlen(rcp) + 1;
|
|
|
+ }
|
|
|
|
|
|
if (slen > len)
|
|
|
rc = -ERANGE;
|
|
|
- else if (copy_to_user(optval, ssp->smk_packet, slen) != 0)
|
|
|
+ else if (copy_to_user(optval, rcp, slen) != 0)
|
|
|
rc = -EFAULT;
|
|
|
|
|
|
if (put_user(slen, optlen) != 0)
|
|
@@ -2982,8 +3010,8 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
|
|
|
|
|
|
{
|
|
|
struct netlbl_lsm_secattr secattr;
|
|
|
- struct socket_smack *sp;
|
|
|
- char smack[SMK_LABELLEN];
|
|
|
+ struct socket_smack *ssp = NULL;
|
|
|
+ char *sp;
|
|
|
int family = PF_UNSPEC;
|
|
|
u32 s = 0; /* 0 is the invalid secid */
|
|
|
int rc;
|
|
@@ -2998,17 +3026,19 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
|
|
|
family = sock->sk->sk_family;
|
|
|
|
|
|
if (family == PF_UNIX) {
|
|
|
- sp = sock->sk->sk_security;
|
|
|
- s = smack_to_secid(sp->smk_out);
|
|
|
+ ssp = sock->sk->sk_security;
|
|
|
+ s = smack_to_secid(ssp->smk_out);
|
|
|
} else if (family == PF_INET || family == PF_INET6) {
|
|
|
/*
|
|
|
* Translate what netlabel gave us.
|
|
|
*/
|
|
|
+ if (sock != NULL && sock->sk != NULL)
|
|
|
+ ssp = sock->sk->sk_security;
|
|
|
netlbl_secattr_init(&secattr);
|
|
|
rc = netlbl_skbuff_getattr(skb, family, &secattr);
|
|
|
if (rc == 0) {
|
|
|
- smack_from_secattr(&secattr, smack);
|
|
|
- s = smack_to_secid(smack);
|
|
|
+ sp = smack_from_secattr(&secattr, ssp);
|
|
|
+ s = smack_to_secid(sp);
|
|
|
}
|
|
|
netlbl_secattr_destroy(&secattr);
|
|
|
}
|
|
@@ -3056,7 +3086,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
|
|
struct netlbl_lsm_secattr secattr;
|
|
|
struct sockaddr_in addr;
|
|
|
struct iphdr *hdr;
|
|
|
- char smack[SMK_LABELLEN];
|
|
|
+ char *sp;
|
|
|
int rc;
|
|
|
struct smk_audit_info ad;
|
|
|
|
|
@@ -3067,9 +3097,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
|
|
netlbl_secattr_init(&secattr);
|
|
|
rc = netlbl_skbuff_getattr(skb, family, &secattr);
|
|
|
if (rc == 0)
|
|
|
- smack_from_secattr(&secattr, smack);
|
|
|
+ sp = smack_from_secattr(&secattr, ssp);
|
|
|
else
|
|
|
- strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN);
|
|
|
+ sp = smack_known_huh.smk_known;
|
|
|
netlbl_secattr_destroy(&secattr);
|
|
|
|
|
|
#ifdef CONFIG_AUDIT
|
|
@@ -3082,7 +3112,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(smack, ssp->smk_in, MAY_WRITE, &ad);
|
|
|
+ rc = smk_access(sp, ssp->smk_in, MAY_WRITE, &ad);
|
|
|
if (rc != 0)
|
|
|
return rc;
|
|
|
|
|
@@ -3090,7 +3120,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
|
|
* Save the peer's label in the request_sock so we can later setup
|
|
|
* smk_packet in the child socket so that SO_PEERCRED can report it.
|
|
|
*/
|
|
|
- req->peer_secid = smack_to_secid(smack);
|
|
|
+ req->peer_secid = smack_to_secid(sp);
|
|
|
|
|
|
/*
|
|
|
* We need to decide if we want to label the incoming connection here
|
|
@@ -3103,7 +3133,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
|
|
if (smack_host_label(&addr) == NULL) {
|
|
|
rcu_read_unlock();
|
|
|
netlbl_secattr_init(&secattr);
|
|
|
- smack_to_secattr(smack, &secattr);
|
|
|
+ smack_to_secattr(sp, &secattr);
|
|
|
rc = netlbl_req_setattr(req, &secattr);
|
|
|
netlbl_secattr_destroy(&secattr);
|
|
|
} else {
|
|
@@ -3125,13 +3155,11 @@ static void smack_inet_csk_clone(struct sock *sk,
|
|
|
const struct request_sock *req)
|
|
|
{
|
|
|
struct socket_smack *ssp = sk->sk_security;
|
|
|
- char *smack;
|
|
|
|
|
|
- if (req->peer_secid != 0) {
|
|
|
- smack = smack_from_secid(req->peer_secid);
|
|
|
- strncpy(ssp->smk_packet, smack, SMK_MAXLEN);
|
|
|
- } else
|
|
|
- ssp->smk_packet[0] = '\0';
|
|
|
+ if (req->peer_secid != 0)
|
|
|
+ ssp->smk_packet = smack_from_secid(req->peer_secid);
|
|
|
+ else
|
|
|
+ ssp->smk_packet = NULL;
|
|
|
}
|
|
|
|
|
|
/*
|