Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "Highlights: - TPM core and driver updates/fixes - IPv6 security labeling (CALIPSO) - Lots of Apparmor fixes - Seccomp: remove 2-phase API, close hole where ptrace can change syscall #" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (156 commits) apparmor: fix SECURITY_APPARMOR_HASH_DEFAULT parameter handling tpm: Add TPM 2.0 support to the Nuvoton i2c driver (NPCT6xx family) tpm: Factor out common startup code tpm: use devm_add_action_or_reset tpm2_i2c_nuvoton: add irq validity check tpm: read burstcount from TPM_STS in one 32-bit transaction tpm: fix byte-order for the value read by tpm2_get_tpm_pt tpm_tis_core: convert max timeouts from msec to jiffies apparmor: fix arg_size computation for when setprocattr is null terminated apparmor: fix oops, validate buffer size in apparmor_setprocattr() apparmor: do not expose kernel stack apparmor: fix module parameters can be changed after policy is locked apparmor: fix oops in profile_unpack() when policy_db is not present apparmor: don't check for vmalloc_addr if kvzalloc() failed apparmor: add missing id bounds check on dfa verification apparmor: allow SYS_CAP_RESOURCE to be sufficient to prlimit another task apparmor: use list_next_entry instead of list_entry_next apparmor: fix refcount race when finding a child profile apparmor: fix ref count leak when profile sha1 hash is read apparmor: check that xindex is in trans_table bounds ...
This commit is contained in:
@@ -22,6 +22,7 @@ ipv6-$(CONFIG_NETFILTER) += netfilter.o
|
||||
ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
|
||||
ipv6-$(CONFIG_PROC_FS) += proc.o
|
||||
ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o
|
||||
ipv6-$(CONFIG_NETLABEL) += calipso.o
|
||||
|
||||
ipv6-objs += $(ipv6-y)
|
||||
|
||||
|
@@ -60,6 +60,7 @@
|
||||
#ifdef CONFIG_IPV6_TUNNEL
|
||||
#include <net/ip6_tunnel.h>
|
||||
#endif
|
||||
#include <net/calipso.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/mroute6.h>
|
||||
@@ -983,6 +984,10 @@ static int __init inet6_init(void)
|
||||
if (err)
|
||||
goto pingv6_fail;
|
||||
|
||||
err = calipso_init();
|
||||
if (err)
|
||||
goto calipso_fail;
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
err = ipv6_sysctl_register();
|
||||
if (err)
|
||||
@@ -993,8 +998,10 @@ out:
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
sysctl_fail:
|
||||
pingv6_exit();
|
||||
calipso_exit();
|
||||
#endif
|
||||
calipso_fail:
|
||||
pingv6_exit();
|
||||
pingv6_fail:
|
||||
ipv6_packet_cleanup();
|
||||
ipv6_packet_fail:
|
||||
|
1473
net/ipv6/calipso.c
Normal file
1473
net/ipv6/calipso.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,7 @@
|
||||
#include <net/ndisc.h>
|
||||
#include <net/ip6_route.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <net/calipso.h>
|
||||
#if IS_ENABLED(CONFIG_IPV6_MIP6)
|
||||
#include <net/xfrm.h>
|
||||
#endif
|
||||
@@ -603,6 +604,28 @@ drop:
|
||||
return false;
|
||||
}
|
||||
|
||||
/* CALIPSO RFC 5570 */
|
||||
|
||||
static bool ipv6_hop_calipso(struct sk_buff *skb, int optoff)
|
||||
{
|
||||
const unsigned char *nh = skb_network_header(skb);
|
||||
|
||||
if (nh[optoff + 1] < 8)
|
||||
goto drop;
|
||||
|
||||
if (nh[optoff + 6] * 4 + 8 > nh[optoff + 1])
|
||||
goto drop;
|
||||
|
||||
if (!calipso_validate(skb, nh + optoff))
|
||||
goto drop;
|
||||
|
||||
return true;
|
||||
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct tlvtype_proc tlvprochopopt_lst[] = {
|
||||
{
|
||||
.type = IPV6_TLV_ROUTERALERT,
|
||||
@@ -612,6 +635,10 @@ static const struct tlvtype_proc tlvprochopopt_lst[] = {
|
||||
.type = IPV6_TLV_JUMBO,
|
||||
.func = ipv6_hop_jumbo,
|
||||
},
|
||||
{
|
||||
.type = IPV6_TLV_CALIPSO,
|
||||
.func = ipv6_hop_calipso,
|
||||
},
|
||||
{ -1, }
|
||||
};
|
||||
|
||||
@@ -758,6 +785,27 @@ static int ipv6_renew_option(void *ohdr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipv6_renew_options - replace a specific ext hdr with a new one.
|
||||
*
|
||||
* @sk: sock from which to allocate memory
|
||||
* @opt: original options
|
||||
* @newtype: option type to replace in @opt
|
||||
* @newopt: new option of type @newtype to replace (user-mem)
|
||||
* @newoptlen: length of @newopt
|
||||
*
|
||||
* Returns a new set of options which is a copy of @opt with the
|
||||
* option type @newtype replaced with @newopt.
|
||||
*
|
||||
* @opt may be NULL, in which case a new set of options is returned
|
||||
* containing just @newopt.
|
||||
*
|
||||
* @newopt may be NULL, in which case the specified option type is
|
||||
* not copied into the new set of options.
|
||||
*
|
||||
* The new set of options is allocated from the socket option memory
|
||||
* buffer of @sk.
|
||||
*/
|
||||
struct ipv6_txoptions *
|
||||
ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
|
||||
int newtype,
|
||||
@@ -830,6 +878,34 @@ out:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipv6_renew_options_kern - replace a specific ext hdr with a new one.
|
||||
*
|
||||
* @sk: sock from which to allocate memory
|
||||
* @opt: original options
|
||||
* @newtype: option type to replace in @opt
|
||||
* @newopt: new option of type @newtype to replace (kernel-mem)
|
||||
* @newoptlen: length of @newopt
|
||||
*
|
||||
* See ipv6_renew_options(). The difference is that @newopt is
|
||||
* kernel memory, rather than user memory.
|
||||
*/
|
||||
struct ipv6_txoptions *
|
||||
ipv6_renew_options_kern(struct sock *sk, struct ipv6_txoptions *opt,
|
||||
int newtype, struct ipv6_opt_hdr *newopt,
|
||||
int newoptlen)
|
||||
{
|
||||
struct ipv6_txoptions *ret_val;
|
||||
const mm_segment_t old_fs = get_fs();
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
ret_val = ipv6_renew_options(sk, opt, newtype,
|
||||
(struct ipv6_opt_hdr __user *)newopt,
|
||||
newoptlen);
|
||||
set_fs(old_fs);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
|
||||
struct ipv6_txoptions *opt)
|
||||
{
|
||||
|
@@ -112,7 +112,7 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
|
||||
}
|
||||
EXPORT_SYMBOL(ipv6_skip_exthdr);
|
||||
|
||||
int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
|
||||
int ipv6_find_tlv(const struct sk_buff *skb, int offset, int type)
|
||||
{
|
||||
const unsigned char *nh = skb_network_header(skb);
|
||||
int packet_len = skb_tail_pointer(skb) - skb_network_header(skb);
|
||||
|
@@ -98,7 +98,6 @@ int ip6_ra_control(struct sock *sk, int sel)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
|
||||
struct ipv6_txoptions *opt)
|
||||
{
|
||||
|
@@ -15,6 +15,9 @@
|
||||
#include <net/ipv6.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <net/inet_frag.h>
|
||||
#ifdef CONFIG_NETLABEL
|
||||
#include <net/calipso.h>
|
||||
#endif
|
||||
|
||||
static int one = 1;
|
||||
static int auto_flowlabels_min;
|
||||
@@ -106,6 +109,22 @@ static struct ctl_table ipv6_rotable[] = {
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = &one
|
||||
},
|
||||
#ifdef CONFIG_NETLABEL
|
||||
{
|
||||
.procname = "calipso_cache_enable",
|
||||
.data = &calipso_cache_enabled,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.procname = "calipso_cache_bucket_size",
|
||||
.data = &calipso_cache_bucketsize,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
#endif /* CONFIG_NETLABEL */
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@@ -443,6 +443,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
|
||||
{
|
||||
struct inet_request_sock *ireq = inet_rsk(req);
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct ipv6_txoptions *opt;
|
||||
struct flowi6 *fl6 = &fl->u.ip6;
|
||||
struct sk_buff *skb;
|
||||
int err = -ENOMEM;
|
||||
@@ -463,8 +464,10 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
|
||||
fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
|
||||
|
||||
rcu_read_lock();
|
||||
err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt),
|
||||
np->tclass);
|
||||
opt = ireq->ipv6_opt;
|
||||
if (!opt)
|
||||
opt = rcu_dereference(np->opt);
|
||||
err = ip6_xmit(sk, skb, fl6, opt, np->tclass);
|
||||
rcu_read_unlock();
|
||||
err = net_xmit_eval(err);
|
||||
}
|
||||
@@ -476,6 +479,7 @@ done:
|
||||
|
||||
static void tcp_v6_reqsk_destructor(struct request_sock *req)
|
||||
{
|
||||
kfree(inet_rsk(req)->ipv6_opt);
|
||||
kfree_skb(inet_rsk(req)->pktopts);
|
||||
}
|
||||
|
||||
@@ -1112,7 +1116,9 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
||||
but we make one more one thing there: reattach optmem
|
||||
to newsk.
|
||||
*/
|
||||
opt = rcu_dereference(np->opt);
|
||||
opt = ireq->ipv6_opt;
|
||||
if (!opt)
|
||||
opt = rcu_dereference(np->opt);
|
||||
if (opt) {
|
||||
opt = ipv6_dup_options(newsk, opt);
|
||||
RCU_INIT_POINTER(newnp->opt, opt);
|
||||
|
Reference in New Issue
Block a user