mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
Merge branch 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/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
This commit is contained in:
commit
10b1eb7d8c
@ -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
|
||||
@ -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,
|
||||
@ -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;
|
||||
|
@ -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);
|
||||
@ -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));
|
||||
@ -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);
|
||||
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
@ -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
|
||||
@ -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)
|
||||
@ -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);
|
||||
|
@ -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 {
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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, dst);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
@ -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),
|
||||
|
@ -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.
|
||||
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user