Skip to content

Commit

Permalink
Merge branch 'next-general' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/jmorris/linux-security

Pull security system updates from James Morris:

 - incorporate new socketpair() hook into LSM and wire up the SELinux
   and Smack modules. From David Herrmann:

     "The idea is to allow SO_PEERSEC to be called on AF_UNIX sockets
      created via socketpair(2), and return the same information as if
      you emulated socketpair(2) via a temporary listener socket.

      Right now SO_PEERSEC will return the unlabeled credentials for a
      socketpair, rather than the actual credentials of the creating
      process."

 - remove the unused security_settime LSM hook (Sargun Dhillon).

 - remove some stack allocated arrays from the keys code (Tycho
   Andersen)

* 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  dh key: get rid of stack allocated array for zeroes
  dh key: get rid of stack allocated array
  big key: get rid of stack array allocation
  smack: provide socketpair callback
  selinux: provide socketpair callback
  net: hook socketpair() into LSM
  security: add hook for socketpair()
  security: remove security_settime
  • Loading branch information
torvalds committed Jun 6, 2018
2 parents d75ae5b + 890e2ab commit 10b1eb7
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 37 deletions.
7 changes: 7 additions & 0 deletions include/linux/lsm_hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,11 @@
* @type contains the requested communications type.
* @protocol contains the requested protocol.
* @kern set to 1 if a kernel socket.
* @socket_socketpair:
* Check permissions before creating a fresh pair of sockets.
* @socka contains the first socket structure.
* @sockb contains the second socket structure.
* Return 0 if permission is granted and the connection was established.
* @socket_bind:
* Check permission before socket protocol layer bind operation is
* performed and the socket @sock is bound to the address specified in the
Expand Down Expand Up @@ -1656,6 +1661,7 @@ union security_list_options {
int (*socket_create)(int family, int type, int protocol, int kern);
int (*socket_post_create)(struct socket *sock, int family, int type,
int protocol, int kern);
int (*socket_socketpair)(struct socket *socka, struct socket *sockb);
int (*socket_bind)(struct socket *sock, struct sockaddr *address,
int addrlen);
int (*socket_connect)(struct socket *sock, struct sockaddr *address,
Expand Down Expand Up @@ -1922,6 +1928,7 @@ struct security_hook_heads {
struct hlist_head unix_may_send;
struct hlist_head socket_create;
struct hlist_head socket_post_create;
struct hlist_head socket_socketpair;
struct hlist_head socket_bind;
struct hlist_head socket_connect;
struct hlist_head socket_listen;
Expand Down
21 changes: 7 additions & 14 deletions include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,6 @@ int security_quotactl(int cmds, int type, int id, struct super_block *sb);
int security_quota_on(struct dentry *dentry);
int security_syslog(int type);
int security_settime64(const struct timespec64 *ts, const struct timezone *tz);
static inline int security_settime(const struct timespec *ts, const struct timezone *tz)
{
struct timespec64 ts64 = timespec_to_timespec64(*ts);

return security_settime64(&ts64, tz);
}
int security_vm_enough_memory_mm(struct mm_struct *mm, long pages);
int security_bprm_set_creds(struct linux_binprm *bprm);
int security_bprm_check(struct linux_binprm *bprm);
Expand Down Expand Up @@ -508,14 +502,6 @@ static inline int security_settime64(const struct timespec64 *ts,
return cap_settime(ts, tz);
}

static inline int security_settime(const struct timespec *ts,
const struct timezone *tz)
{
struct timespec64 ts64 = timespec_to_timespec64(*ts);

return cap_settime(&ts64, tz);
}

static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
{
return __vm_enough_memory(mm, pages, cap_vm_enough_memory(mm, pages));
Expand Down Expand Up @@ -1191,6 +1177,7 @@ int security_unix_may_send(struct socket *sock, struct socket *other);
int security_socket_create(int family, int type, int protocol, int kern);
int security_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern);
int security_socket_socketpair(struct socket *socka, struct socket *sockb);
int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen);
int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen);
int security_socket_listen(struct socket *sock, int backlog);
Expand Down Expand Up @@ -1262,6 +1249,12 @@ static inline int security_socket_post_create(struct socket *sock,
return 0;
}

static inline int security_socket_socketpair(struct socket *socka,
struct socket *sockb)
{
return 0;
}

static inline int security_socket_bind(struct socket *sock,
struct sockaddr *address,
int addrlen)
Expand Down
7 changes: 7 additions & 0 deletions net/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,13 @@ int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
goto out;
}

err = security_socket_socketpair(sock1, sock2);
if (unlikely(err)) {
sock_release(sock2);
sock_release(sock1);
goto out;
}

err = sock1->ops->socketpair(sock1, sock2);
if (unlikely(err < 0)) {
sock_release(sock2);
Expand Down
11 changes: 10 additions & 1 deletion security/keys/big_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <keys/user-type.h>
#include <keys/big_key-type.h>
#include <crypto/aead.h>
#include <crypto/gcm.h>

struct big_key_buf {
unsigned int nr_pages;
Expand Down Expand Up @@ -85,6 +86,7 @@ struct key_type key_type_big_key = {
* Crypto names for big_key data authenticated encryption
*/
static const char big_key_alg_name[] = "gcm(aes)";
#define BIG_KEY_IV_SIZE GCM_AES_IV_SIZE

/*
* Crypto algorithms for big_key data authenticated encryption
Expand All @@ -109,7 +111,7 @@ static int big_key_crypt(enum big_key_op op, struct big_key_buf *buf, size_t dat
* an .update function, so there's no chance we'll wind up reusing the
* key to encrypt updated data. Simply put: one key, one encryption.
*/
u8 zero_nonce[crypto_aead_ivsize(big_key_aead)];
u8 zero_nonce[BIG_KEY_IV_SIZE];

aead_req = aead_request_alloc(big_key_aead, GFP_KERNEL);
if (!aead_req)
Expand Down Expand Up @@ -425,6 +427,13 @@ static int __init big_key_init(void)
pr_err("Can't alloc crypto: %d\n", ret);
return ret;
}

if (unlikely(crypto_aead_ivsize(big_key_aead) != BIG_KEY_IV_SIZE)) {
WARN(1, "big key algorithm changed?");
ret = -EINVAL;
goto free_aead;
}

ret = crypto_aead_setauthsize(big_key_aead, ENC_AUTHTAG_SIZE);
if (ret < 0) {
pr_err("Can't set crypto auth tag len: %d\n", ret);
Expand Down
35 changes: 13 additions & 22 deletions security/keys/dh.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,
goto err;

if (zlen && h) {
u8 tmpbuffer[h];
size_t chunk = min_t(size_t, zlen, h);
u8 tmpbuffer[32];
size_t chunk = min_t(size_t, zlen, sizeof(tmpbuffer));
memset(tmpbuffer, 0, chunk);

do {
Expand All @@ -173,7 +173,7 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,
goto err;

zlen -= chunk;
chunk = min_t(size_t, zlen, h);
chunk = min_t(size_t, zlen, sizeof(tmpbuffer));
} while (zlen);
}

Expand All @@ -183,24 +183,13 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,
goto err;
}

if (dlen < h) {
u8 tmpbuffer[h];

err = crypto_shash_final(desc, tmpbuffer);
if (err)
goto err;
memcpy(dst, tmpbuffer, dlen);
memzero_explicit(tmpbuffer, h);
return 0;
} else {
err = crypto_shash_final(desc, dst);
if (err)
goto err;
err = crypto_shash_final(desc, dst);
if (err)
goto err;

dlen -= h;
dst += h;
counter = cpu_to_be32(be32_to_cpu(counter) + 1);
}
dlen -= h;
dst += h;
counter = cpu_to_be32(be32_to_cpu(counter) + 1);
}

return 0;
Expand All @@ -216,14 +205,16 @@ static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc,
{
uint8_t *outbuf = NULL;
int ret;
size_t outbuf_len = round_up(buflen,
crypto_shash_digestsize(sdesc->shash.tfm));

outbuf = kmalloc(buflen, GFP_KERNEL);
outbuf = kmalloc(outbuf_len, GFP_KERNEL);
if (!outbuf) {
ret = -ENOMEM;
goto err;
}

ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, buflen, lzero);
ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, outbuf_len, lzero);
if (ret)
goto err;

Expand Down
6 changes: 6 additions & 0 deletions security/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,12 @@ int security_socket_post_create(struct socket *sock, int family,
protocol, kern);
}

int security_socket_socketpair(struct socket *socka, struct socket *sockb)
{
return call_int_hook(socket_socketpair, 0, socka, sockb);
}
EXPORT_SYMBOL(security_socket_socketpair);

int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
{
return call_int_hook(socket_bind, 0, sock, address, addrlen);
Expand Down
13 changes: 13 additions & 0 deletions security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -4580,6 +4580,18 @@ static int selinux_socket_post_create(struct socket *sock, int family,
return err;
}

static int selinux_socket_socketpair(struct socket *socka,
struct socket *sockb)
{
struct sk_security_struct *sksec_a = socka->sk->sk_security;
struct sk_security_struct *sksec_b = sockb->sk->sk_security;

sksec_a->peer_sid = sksec_b->sid;
sksec_b->peer_sid = sksec_a->sid;

return 0;
}

/* Range of port numbers used to automatically bind.
Need to determine whether we should perform a name_bind
permission check between the socket and the port number. */
Expand Down Expand Up @@ -7016,6 +7028,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {

LSM_HOOK_INIT(socket_create, selinux_socket_create),
LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
LSM_HOOK_INIT(socket_socketpair, selinux_socket_socketpair),
LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
Expand Down
22 changes: 22 additions & 0 deletions security/smack/smack_lsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2842,6 +2842,27 @@ static int smack_socket_post_create(struct socket *sock, int family,
return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
}

/**
* smack_socket_socketpair - create socket pair
* @socka: one socket
* @sockb: another socket
*
* Cross reference the peer labels for SO_PEERSEC
*
* Returns 0 on success, and error code otherwise
*/
static int smack_socket_socketpair(struct socket *socka,
struct socket *sockb)
{
struct socket_smack *asp = socka->sk->sk_security;
struct socket_smack *bsp = sockb->sk->sk_security;

asp->smk_packet = bsp->smk_out;
bsp->smk_packet = asp->smk_out;

return 0;
}

#ifdef SMACK_IPV6_PORT_LABELING
/**
* smack_socket_bind - record port binding information.
Expand Down Expand Up @@ -4724,6 +4745,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(unix_may_send, smack_unix_may_send),

LSM_HOOK_INIT(socket_post_create, smack_socket_post_create),
LSM_HOOK_INIT(socket_socketpair, smack_socket_socketpair),
#ifdef SMACK_IPV6_PORT_LABELING
LSM_HOOK_INIT(socket_bind, smack_socket_bind),
#endif
Expand Down

0 comments on commit 10b1eb7

Please sign in to comment.