Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp4666377yba; Wed, 17 Apr 2019 16:54:41 -0700 (PDT) X-Google-Smtp-Source: APXvYqxOgd9Red+ULDXd3YhzIvd6XSS9YeFiQZtbH/BIGPA/VUxllRV+aLFugo6toYsW5/Dm+CNE X-Received: by 2002:a63:d349:: with SMTP id u9mr5906709pgi.83.1555545281817; Wed, 17 Apr 2019 16:54:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1555545281; cv=none; d=google.com; s=arc-20160816; b=baEG4KrwmwvSm0A3yEf1Z/jjkxlDOtIK7hjbhbnr4s1CSFqwkSvGmH51f4UHxwslZS /fuvHPB54fGrwk2LPbACN1GVZle4wSt9mmgtJPUuxIWdkGUOvsyMQxClICML7V1cRBx/ A4QS0cRaZ0Y0eE5LCidRYZtQNlY0Pd6vW/gIhxEcxZmjJfYCy5h6uK0E5iUV8wrxYrqz JEUPAf223d6BZDPzZdXoh1FQ4SVZCFOxG+SOOT6lWhicCMucK/vNAiaSQNm8635/MaSK djOKgUjemwigzPN8fHHov55zhHzY21AqotznkcF9sllu5RTsifTGi9a01AOeB1hYLGFH OeAQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date; bh=Jq5NvCglmQDaN2itcTeGgGumIQS6zTEc4e55vqf6IgI=; b=pSw1zV+fre1qcuT6tjc/3bqEdMJQNzY+MXEQBbDgrt1NCvMxbDPTq2f/ZfNb//krsl MjBTpJZkbDJPZYU9zZbzcDSwbUDj4d9UWRsNe5F/Rk8bCReXxLv3iIZRuozKaijOcvja LtFSD4c6ULfFXC+Lb1gJNBV6yxHGJWVLBYNQ1QdA6DcPs7qWxLZ4Rlbz6SRZunTaJfax /0bJEZIjCLBlSybgdo+IHwHy/0M/XbU0aZmz5ncajdiDbgaWo3Hsp2snRj9l/nZsyiVj 9fmZobh1bP3l/fzBzXOGvzaCvuCl1paqxnnYXPNph/yzMXCchUH3QFuuBE9X1FcaHchN Wv5g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id gn14si370838plb.7.2019.04.17.16.54.26; Wed, 17 Apr 2019 16:54:41 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387680AbfDQXxG (ORCPT + 99 others); Wed, 17 Apr 2019 19:53:06 -0400 Received: from zeniv.linux.org.uk ([195.92.253.2]:52892 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729331AbfDQXxG (ORCPT ); Wed, 17 Apr 2019 19:53:06 -0400 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.92 #3 (Red Hat Linux)) id 1hGuMO-0002nr-SI; Wed, 17 Apr 2019 23:53:01 +0000 Date: Thu, 18 Apr 2019 00:53:00 +0100 From: Al Viro To: Arnd Bergmann Cc: Linux FS-devel Mailing List , y2038 Mailman List , Linux Kernel Mailing List , Paul Mackerras , "David S. Miller" , Michal Ostrowski , Dmitry Kozlov , James Chapman , linux-ppp@vger.kernel.org, Networking Subject: Re: [PATCH v3 02/26] compat_ioctl: move simple ppp command handling into driver Message-ID: <20190417235300.GB2217@ZenIV.linux.org.uk> References: <20190416202013.4034148-1-arnd@arndb.de> <20190416202013.4034148-3-arnd@arndb.de> <20190417211303.GU2217@ZenIV.linux.org.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Apr 18, 2019 at 12:03:07AM +0200, Arnd Bergmann wrote: > On Wed, Apr 17, 2019 at 11:13 PM Al Viro wrote: > > > > On Tue, Apr 16, 2019 at 10:19:40PM +0200, Arnd Bergmann wrote: > > > diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c > > > index c708400fff4a..04252c3492ee 100644 > > > --- a/drivers/net/ppp/ppp_generic.c > > > +++ b/drivers/net/ppp/ppp_generic.c > > > @@ -899,6 +899,7 @@ static const struct file_operations ppp_device_fops = { > > > .write = ppp_write, > > > .poll = ppp_poll, > > > .unlocked_ioctl = ppp_ioctl, > > > + .compat_ioctl = ppp_ioctl, > > > > Oh? What happens on e.g. s390 with something like PPPIOCNEWUNIT? > > Current kernel: > > * no ->compat_ioctl() > > * ->unlock_ioctl() is present > > * found by compat_ioctl_check_table() > > * pass (unsigned long)compat_ptr(arg) to do_vfs_ioctl() > > * pass that to ppp_ioctl() > > * pass that to ppp_unattached_ioctl() > > * fetch int from (int __user *)compat_ptr(arg) > > > > With your patch: > > * call ppp_ioctl() > > * pass arg to ppp_unattached_ioctl() > > * fetch int from (int __user *)arg > > > > AFAICS, that's broken... > > Correct. I had added this patch to the series from an older set of > patches (predating > the compat_ptr_ioctl() series) , and did not check for this issue again. When > I originally created the patch, I assumed that even on s390 it would be no > problem. > > > Looking at that ppp_ioctl(), > > pointer to arch-independent type or ignored: > > PPPIOCNEWUNIT PPPIOCATTACH PPPIOCATTCHAN PPPIOCSMRU PPPIOCSFLAGS > > PPPIOCGFLAGS PPPIOCGUNIT PPPIOCSDEBUG PPPIOCSMAXCID PPPIOCCONNECT > > PPPIOCGDEBUG PPPIOCSMAXCID PPPIOCSMRRU > > PPPIOCDETACH PPPIOCDISCONN > > PPPIOCGASYNCMAP PPPIOCSASYNCMAP PPPIOCGRASYNCMAP PPPIOCSRASYNCMAP > > PPPIOCGXASYNCMAP PPPIOCSXASYNCMAP > > PPPIOCGNPMODE PPPIOCSNPMODE > > pointer to struct ppp_option_data (with further pointer-chasing in it): > > PPPIOCSCOMPRESS > > pointer to struct ppp_idle: > > PPPIOCGIDLE > > pointer to struct sock_filter (with hidden pointer-chasing, AFAICS): > > PPPIOCSPASS PPPIOCSACTIVE > > > > Pretty much all of them take pointers. What's more, reaction to > > unknown is -ENOTTY, not -ENOIOCTLCM, so that patch will have > > prevent the translated ones from reaching do_ioctl_trans() > > Good point, this patch sequence does break bisection. > > > What am I missing here? Why not simply do > > > > compat_ppp_ioctl() > > { > > PPPIOCSCOMPRESS32 => deal with it > > PPPIOCGIDLE32 => deal with it > > PPPIOCSPASS32 / PPPIOCSACTIVE32 => deal with it > > default: pass compat_ptr(arg) to ppp_ioctl() and be done with that > > } > > > > with BPF-related bits (both compat and native) taken to e.g. net/core/bpf-ppp.c, > > picked by both generic and isdn? IDGI... > > I was trying to unify the native and compat code paths as much > as possible here. Handling the four PPPIO*32 commands in > compat_ppp_ioctl would either require duplicating large chunks > of ppp_ioctl, or keeping the extra compat_alloc_user_space() > copy from the existing implementation. > > I'll try to come up with a different way to structure the patches. Huh? Instead of case PPPIOCSCOMPRESS: err = ppp_set_compress(ppp, arg); break; in native, have struct ppp_option_data data; ... case PPPIOCSCOMPRESS: if (copy_from_user(&data, argp, sizeof(data))) err = -EFAULT; else err = ppp_set_compress(ppp, &data); break; while in compat do struct ppp_option_data32 data32; case PPPIOCSCOMPRESS32: if (copy_from_user(&data32, argp, sizeof(data32))) err = -EFAULT; else err = ppp_set_compress(ppp, &(struct ppp_option_data){ .ptr = compat_ptr(data32.ptr), .length = data32.length, .transmit = data32.transmit }); break; PPPIOCGIDLE is small to start with - not a lot to copy there. And as for the filters... What you need is something like struct bpf_prog *get_ppp_bpf(struct sock_fprog __user *p) { struct sock_fprog uprog; struct sock_fprog_kern fprog; struct sock_filter *code = NULL; struct bpf_prog *res; int err; if (copy_from_user(&uprog, p, sizeof(uprog))) return ERR_PTR(-EFAULT); if (!uprog.len) return NULL; fprog.len = uprog.len * sizeof(struct sock_filter); code = fprog.filter = memdup_user(uprog.filter, fprog.len); if (IS_ERR(code)) return ERR_CAST(code); err = bpf_prog_create(&res, &fprog); kfree(code); if (err) return ERR_PTR(err); return res; } in net/core/ppp-filter.c (or in net/core/filter.c, for that matter, under appropriate ifdef)) with obvious compat counterpart next to it. Hell, turn the above into static struct bpf_prog *__get_ppp_bpf(struct sock_fprog *kp) { struct sock_fprog_kern fprog; struct sock_filter *code = NULL; struct bpf_prog *res; int err; if (!kp->len) return NULL; fprog.len = kp->len * sizeof(struct sock_filter); code = fprog.filter = memdup_user(kp->filter, fprog.len); if (IS_ERR(code)) return ERR_CAST(code); err = bpf_prog_create(&res, &fprog); kfree(code); if (err) return ERR_PTR(err); return res; } struct bpf_prog *get_ppp_bpf(struct sock_fprog __user *p) { struct sock_fprog uprog; if (copy_from_user(&uprog, p, sizeof(uprog))) return ERR_PTR(-EFAULT); return __get_ppp_bpf(&uprog); } struct bpf_prog *compat_get_ppp_bpf(struct sock_fprog32 __user *p) { struct sock_fprog uprog32; if (copy_from_user(&uprog32, p, sizeof(uprog32))) return ERR_PTR(-EFAULT); return __get_ppp_bpf(&(struct sock_fprog){ .len = uprog32.len, .filter = compat_ptr(uprog32.filter)}); } Then in native ioctl do case PPPIOCSPASS: case PPPIOCSACTIVE: { struct bpf_prog *filter = get_bpf_ppp(argp); if (IS_ERR(filter)) { err = PTR_ERR(filter); } else { struct bpf_prog **which; if (cmd == PPPIOCSPASS) which = &ppp->pass_filter; else which = &ppp->active_filter; ppp_lock(ppp); if (*which) bpf_prog_destroy(*which); *which = filter; ppp_unlock(ppp); err = 0; } break; } in native and similar in compat, with get_bpf_ppp() replaced with call of compat_get_bpf_ppp() and ioctl numbers obviously adjusted. All there is to it... Helpers obviously shared with isdn and yes, all crap gone from fs/compat_ioctl.c... Why would you want to duplicate large chunks of anything? The above is not even compile-tested, but... I can put together a patch if you wish. Or am I missing something here?