Commit b1fcd35c authored by Daniel Borkmann's avatar Daniel Borkmann Committed by David S. Miller

net: filter: let unattached filters use sock_fprog_kern

The sk_unattached_filter_create() API is used by BPF filters that
are not directly attached or related to sockets, and are used in
team, ptp, xt_bpf, cls_bpf, etc. As such all users do their own
internal managment of obtaining filter blocks and thus already
have them in kernel memory and set up before calling into
sk_unattached_filter_create(). As a result, due to __user annotation
in sock_fprog, sparse triggers false positives (incorrect type in
assignment [different address space]) when filters are set up before
passing them to sk_unattached_filter_create(). Therefore, let
sk_unattached_filter_create() API use sock_fprog_kern to overcome
this issue.
Signed-off-by: default avatarDaniel Borkmann <dborkman@redhat.com>
Acked-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8556ce79
...@@ -634,7 +634,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) ...@@ -634,7 +634,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
#ifdef CONFIG_IPPP_FILTER #ifdef CONFIG_IPPP_FILTER
case PPPIOCSPASS: case PPPIOCSPASS:
{ {
struct sock_fprog fprog; struct sock_fprog_kern fprog;
struct sock_filter *code; struct sock_filter *code;
int err, len = get_filter(argp, &code); int err, len = get_filter(argp, &code);
...@@ -653,7 +653,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) ...@@ -653,7 +653,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
} }
case PPPIOCSACTIVE: case PPPIOCSACTIVE:
{ {
struct sock_fprog fprog; struct sock_fprog_kern fprog;
struct sock_filter *code; struct sock_filter *code;
int err, len = get_filter(argp, &code); int err, len = get_filter(argp, &code);
......
...@@ -757,7 +757,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -757,7 +757,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
err = get_filter(argp, &code); err = get_filter(argp, &code);
if (err >= 0) { if (err >= 0) {
struct sock_fprog fprog = { struct sock_fprog_kern fprog = {
.len = err, .len = err,
.filter = code, .filter = code,
}; };
...@@ -778,7 +778,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -778,7 +778,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
err = get_filter(argp, &code); err = get_filter(argp, &code);
if (err >= 0) { if (err >= 0) {
struct sock_fprog fprog = { struct sock_fprog_kern fprog = {
.len = err, .len = err,
.filter = code, .filter = code,
}; };
......
...@@ -49,7 +49,7 @@ struct lb_port_mapping { ...@@ -49,7 +49,7 @@ struct lb_port_mapping {
struct lb_priv_ex { struct lb_priv_ex {
struct team *team; struct team *team;
struct lb_port_mapping tx_hash_to_port_mapping[LB_TX_HASHTABLE_SIZE]; struct lb_port_mapping tx_hash_to_port_mapping[LB_TX_HASHTABLE_SIZE];
struct sock_fprog *orig_fprog; struct sock_fprog_kern *orig_fprog;
struct { struct {
unsigned int refresh_interval; /* in tenths of second */ unsigned int refresh_interval; /* in tenths of second */
struct delayed_work refresh_dw; struct delayed_work refresh_dw;
...@@ -241,10 +241,10 @@ static int lb_bpf_func_get(struct team *team, struct team_gsetter_ctx *ctx) ...@@ -241,10 +241,10 @@ static int lb_bpf_func_get(struct team *team, struct team_gsetter_ctx *ctx)
return 0; return 0;
} }
static int __fprog_create(struct sock_fprog **pfprog, u32 data_len, static int __fprog_create(struct sock_fprog_kern **pfprog, u32 data_len,
const void *data) const void *data)
{ {
struct sock_fprog *fprog; struct sock_fprog_kern *fprog;
struct sock_filter *filter = (struct sock_filter *) data; struct sock_filter *filter = (struct sock_filter *) data;
if (data_len % sizeof(struct sock_filter)) if (data_len % sizeof(struct sock_filter))
...@@ -262,7 +262,7 @@ static int __fprog_create(struct sock_fprog **pfprog, u32 data_len, ...@@ -262,7 +262,7 @@ static int __fprog_create(struct sock_fprog **pfprog, u32 data_len,
return 0; return 0;
} }
static void __fprog_destroy(struct sock_fprog *fprog) static void __fprog_destroy(struct sock_fprog_kern *fprog)
{ {
kfree(fprog->filter); kfree(fprog->filter);
kfree(fprog); kfree(fprog);
...@@ -273,7 +273,7 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx) ...@@ -273,7 +273,7 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
struct lb_priv *lb_priv = get_lb_priv(team); struct lb_priv *lb_priv = get_lb_priv(team);
struct sk_filter *fp = NULL; struct sk_filter *fp = NULL;
struct sk_filter *orig_fp; struct sk_filter *orig_fp;
struct sock_fprog *fprog = NULL; struct sock_fprog_kern *fprog = NULL;
int err; int err;
if (ctx->data.bin_val.len) { if (ctx->data.bin_val.len) {
......
...@@ -188,7 +188,7 @@ int sk_convert_filter(struct sock_filter *prog, int len, ...@@ -188,7 +188,7 @@ int sk_convert_filter(struct sock_filter *prog, int len,
struct sock_filter_int *new_prog, int *new_len); struct sock_filter_int *new_prog, int *new_len);
int sk_unattached_filter_create(struct sk_filter **pfp, int sk_unattached_filter_create(struct sk_filter **pfp,
struct sock_fprog *fprog); struct sock_fprog_kern *fprog);
void sk_unattached_filter_destroy(struct sk_filter *fp); void sk_unattached_filter_destroy(struct sk_filter *fp);
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
......
...@@ -1472,7 +1472,7 @@ static int run_one(struct sk_filter *fp, struct bpf_test *t) ...@@ -1472,7 +1472,7 @@ static int run_one(struct sk_filter *fp, struct bpf_test *t)
static __init int test_bpf(void) static __init int test_bpf(void)
{ {
struct sk_filter *fp, *fp_ext = NULL; struct sk_filter *fp, *fp_ext = NULL;
struct sock_fprog fprog; struct sock_fprog_kern fprog;
int err, i, err_cnt = 0; int err, i, err_cnt = 0;
for (i = 0; i < ARRAY_SIZE(tests); i++) { for (i = 0; i < ARRAY_SIZE(tests); i++) {
......
...@@ -1585,7 +1585,7 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp, ...@@ -1585,7 +1585,7 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp,
* a negative errno code is returned. On success the return is zero. * a negative errno code is returned. On success the return is zero.
*/ */
int sk_unattached_filter_create(struct sk_filter **pfp, int sk_unattached_filter_create(struct sk_filter **pfp,
struct sock_fprog *fprog) struct sock_fprog_kern *fprog)
{ {
unsigned int fsize = sk_filter_proglen(fprog); unsigned int fsize = sk_filter_proglen(fprog);
struct sk_filter *fp; struct sk_filter *fp;
......
...@@ -133,7 +133,7 @@ void __init ptp_classifier_init(void) ...@@ -133,7 +133,7 @@ void __init ptp_classifier_init(void)
{ 0x16, 0, 0, 0x00000000 }, { 0x16, 0, 0, 0x00000000 },
{ 0x06, 0, 0, 0x00000000 }, { 0x06, 0, 0, 0x00000000 },
}; };
struct sock_fprog ptp_prog = { struct sock_fprog_kern ptp_prog = {
.len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter, .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter,
}; };
......
...@@ -23,10 +23,11 @@ MODULE_ALIAS("ip6t_bpf"); ...@@ -23,10 +23,11 @@ MODULE_ALIAS("ip6t_bpf");
static int bpf_mt_check(const struct xt_mtchk_param *par) static int bpf_mt_check(const struct xt_mtchk_param *par)
{ {
struct xt_bpf_info *info = par->matchinfo; struct xt_bpf_info *info = par->matchinfo;
struct sock_fprog program; struct sock_fprog_kern program;
program.len = info->bpf_program_num_elem; program.len = info->bpf_program_num_elem;
program.filter = (struct sock_filter __user *) info->bpf_program; program.filter = info->bpf_program;
if (sk_unattached_filter_create(&info->filter, &program)) { if (sk_unattached_filter_create(&info->filter, &program)) {
pr_info("bpf: check failed: parse error\n"); pr_info("bpf: check failed: parse error\n");
return -EINVAL; return -EINVAL;
......
...@@ -160,7 +160,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, ...@@ -160,7 +160,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
{ {
struct sock_filter *bpf_ops, *bpf_old; struct sock_filter *bpf_ops, *bpf_old;
struct tcf_exts exts; struct tcf_exts exts;
struct sock_fprog tmp; struct sock_fprog_kern tmp;
struct sk_filter *fp, *fp_old; struct sk_filter *fp, *fp_old;
u16 bpf_size, bpf_len; u16 bpf_size, bpf_len;
u32 classid; u32 classid;
...@@ -191,7 +191,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, ...@@ -191,7 +191,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
memcpy(bpf_ops, nla_data(tb[TCA_BPF_OPS]), bpf_size); memcpy(bpf_ops, nla_data(tb[TCA_BPF_OPS]), bpf_size);
tmp.len = bpf_len; tmp.len = bpf_len;
tmp.filter = (struct sock_filter __user *) bpf_ops; tmp.filter = bpf_ops;
ret = sk_unattached_filter_create(&fp, &tmp); ret = sk_unattached_filter_create(&fp, &tmp);
if (ret) if (ret)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment