From patchwork Mon Jan 2 22:19:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Willem de Bruijn X-Patchwork-Id: 710311 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3tss4z3jKMz9t0Z for ; Tue, 3 Jan 2017 09:22:11 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="UQwn0j6N"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934287AbdABWUa (ORCPT ); Mon, 2 Jan 2017 17:20:30 -0500 Received: from mail-qk0-f196.google.com ([209.85.220.196]:34548 "EHLO mail-qk0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934263AbdABWT7 (ORCPT ); Mon, 2 Jan 2017 17:19:59 -0500 Received: by mail-qk0-f196.google.com with SMTP id t184so48318727qkd.1; Mon, 02 Jan 2017 14:19:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=7c9XQa+BiVU/tdB1cvJIRh5pGLb183bbfM04aYtGuI4=; b=UQwn0j6NJs680LzEuGhsgjVbonJyOVtGSkDSE/WEz17hATF+Hq3VLZShgVWPp1Ij2X Hp903qouIda3xEjYvznPr/D0gMTDESNqP/Cw03lqEnqJJIJaSm+Psesm7hKeAk3TLf/S MfG8PBSFT7r6NxrziNIYXNKpZnt3/ykTFCI/b5h4IipnGeINcYY/cM2KUGh1mz3phps1 itJxaX6kTYszXr7Mwc8fxZd798hsHf2cXqdPKV7rp4MsJa15EIbhCSy8IqTs/HjgjPCo pTY2Z2CLl8hh5ZCFHSy3bIjUNk2iGo7fPAAj87c0Ykudd7rAu9GEvegCMcsSr2MOFFW+ +rFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=7c9XQa+BiVU/tdB1cvJIRh5pGLb183bbfM04aYtGuI4=; b=O4WXxwt3fNqV8hfp36ppBKCALDJnfoKsrEZg+EteMiFMZFtzZsWwbgahNg8v/zVHyZ up02i/TkbbKN+oIjJdHh/DH+lseJGMocP2PC7Tuqulmn+1xJ4JBnhpCdb5zolUZjKNBr WNm78Cbu28Mfe6GR3etj0rzhEAEySCIoylms7M0fq9P1c8j5PqzwC1FVsp6pZbsGAHab +TSJHQ26Pf5U0sIUxquD0Ay/TunH18w8aIji11OmWNNBUCy+c+miHZmfUUX1xsKJYu/U REulUJoD9Q+XW+dgYK4WDhzPL7X4pYWbSotMduSsh/KUiak6ENPS/t0AfM1dq5+9zGV7 2hSg== X-Gm-Message-State: AIkVDXI56SK3GZsbm2Eyj6kLDUxVgKWT43qNvUDFryzdr5DHGfN+xgf9lXbFfO26y/Az2Q== X-Received: by 10.55.164.135 with SMTP id n129mr32866052qke.170.1483395598222; Mon, 02 Jan 2017 14:19:58 -0800 (PST) Received: from willemb1.nyc.corp.google.com ([100.101.230.128]) by smtp.gmail.com with ESMTPSA id 7sm31611293qkx.49.2017.01.02.14.19.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 02 Jan 2017 14:19:57 -0800 (PST) From: Willem de Bruijn To: netfilter-devel@vger.kernel.org Cc: netdev@vger.kernel.org, davem@davemloft.net, fw@strlen.de, dborkman@iogearbox.net, pablo@netfilter.org, Willem de Bruijn Subject: [PATCH nf-next 5/7] ebtables: use match, target and data copy_to_user helpers Date: Mon, 2 Jan 2017 17:19:44 -0500 Message-Id: <1483395586-105774-6-git-send-email-willemdebruijn.kernel@gmail.com> X-Mailer: git-send-email 2.8.0.rc3.226.g39d4020 In-Reply-To: <1483395586-105774-1-git-send-email-willemdebruijn.kernel@gmail.com> References: <1483395586-105774-1-git-send-email-willemdebruijn.kernel@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Willem de Bruijn Convert ebtables to copying entries, matches and targets one by one. The solution is analogous to that of generic xt_(match|target)_to_user helpers, but is applied to different structs. Convert existing helpers ebt_make_XXXname helpers that overwrite fields of an already copy_to_user'd struct with ebt_XXX_to_user helpers that copy all relevant fields of the struct from scratch. Signed-off-by: Willem de Bruijn --- net/bridge/netfilter/ebtables.c | 78 +++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 537e3d5..79b6991 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1346,56 +1346,72 @@ static int update_counters(struct net *net, const void __user *user, hlp.num_counters, user, len); } -static inline int ebt_make_matchname(const struct ebt_entry_match *m, - const char *base, char __user *ubase) +static inline int ebt_obj_to_user(char __user *um, const char *_name, + const char *data, int entrysize, + int usersize, int datasize) { - char __user *hlp = ubase + ((char *)m - base); - char name[EBT_FUNCTION_MAXNAMELEN] = {}; + char name[EBT_FUNCTION_MAXNAMELEN] = {0}; /* ebtables expects 32 bytes long names but xt_match names are 29 bytes * long. Copy 29 bytes and fill remaining bytes with zeroes. */ - strlcpy(name, m->u.match->name, sizeof(name)); - if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN)) + strlcpy(name, _name, sizeof(name)); + if (copy_to_user(um, name, EBT_FUNCTION_MAXNAMELEN) || + put_user(datasize, (int __user *)(um + EBT_FUNCTION_MAXNAMELEN)) || + xt_data_to_user(um + entrysize, data, usersize, datasize)) return -EFAULT; + return 0; } -static inline int ebt_make_watchername(const struct ebt_entry_watcher *w, - const char *base, char __user *ubase) +static inline int ebt_match_to_user(const struct ebt_entry_match *m, + const char *base, char __user *ubase) { - char __user *hlp = ubase + ((char *)w - base); - char name[EBT_FUNCTION_MAXNAMELEN] = {}; + return ebt_obj_to_user(ubase + ((char *)m - base), + m->u.match->name, m->data, sizeof(*m), + m->u.match->usersize, m->match_size); +} - strlcpy(name, w->u.watcher->name, sizeof(name)); - if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN)) - return -EFAULT; - return 0; +static inline int ebt_watcher_to_user(const struct ebt_entry_watcher *w, + const char *base, char __user *ubase) +{ + return ebt_obj_to_user(ubase + ((char *)w - base), + w->u.watcher->name, w->data, sizeof(*w), + w->u.watcher->usersize, w->watcher_size); } -static inline int ebt_make_names(struct ebt_entry *e, const char *base, - char __user *ubase) +static inline int ebt_entry_to_user(struct ebt_entry *e, const char *base, + char __user *ubase) { int ret; char __user *hlp; const struct ebt_entry_target *t; - char name[EBT_FUNCTION_MAXNAMELEN] = {}; - if (e->bitmask == 0) + if (e->bitmask == 0) { + /* special case !EBT_ENTRY_OR_ENTRIES */ + if (copy_to_user(ubase + ((char *)e - base), e, + sizeof(struct ebt_entries))) + return -EFAULT; return 0; + } + + if (copy_to_user(ubase + ((char *)e - base), e, sizeof(*e))) + return -EFAULT; hlp = ubase + (((char *)e + e->target_offset) - base); t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); - ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase); + ret = EBT_MATCH_ITERATE(e, ebt_match_to_user, base, ubase); if (ret != 0) return ret; - ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase); + ret = EBT_WATCHER_ITERATE(e, ebt_watcher_to_user, base, ubase); if (ret != 0) return ret; - strlcpy(name, t->u.target->name, sizeof(name)); - if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN)) - return -EFAULT; + ret = ebt_obj_to_user(hlp, t->u.target->name, t->data, sizeof(*t), + t->u.target->usersize, t->target_size); + if (ret != 0) + return ret; + return 0; } @@ -1475,13 +1491,9 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user, if (ret) return ret; - if (copy_to_user(tmp.entries, entries, entries_size)) { - BUGPRINT("Couldn't copy entries to userspace\n"); - return -EFAULT; - } /* set the match/watcher/target names right */ return EBT_ENTRY_ITERATE(entries, entries_size, - ebt_make_names, entries, tmp.entries); + ebt_entry_to_user, entries, tmp.entries); } static int do_ebt_set_ctl(struct sock *sk, @@ -1630,8 +1642,10 @@ static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr, if (match->compat_to_user) { if (match->compat_to_user(cm->data, m->data)) return -EFAULT; - } else if (copy_to_user(cm->data, m->data, msize)) + } else { + if (xt_data_to_user(cm->data, m->data, match->usersize, msize)) return -EFAULT; + } *size -= ebt_compat_entry_padsize() + off; *dstptr = cm->data; @@ -1657,8 +1671,10 @@ static int compat_target_to_user(struct ebt_entry_target *t, if (target->compat_to_user) { if (target->compat_to_user(cm->data, t->data)) return -EFAULT; - } else if (copy_to_user(cm->data, t->data, tsize)) - return -EFAULT; + } else { + if (xt_data_to_user(cm->data, t->data, target->usersize, tsize)) + return -EFAULT; + } *size -= ebt_compat_entry_padsize() + off; *dstptr = cm->data;