eventfd: strictly check the count parameter of eventfd_write to avoid inputting illegal strings
Message ID | tencent_10AAA44731FFFA493F9F5501521F07DD4D0A@qq.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel+bounces-55328-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:168b:b0:106:860b:bbdd with SMTP id ma11csp1684452dyb; Tue, 6 Feb 2024 09:09:30 -0800 (PST) X-Google-Smtp-Source: AGHT+IHBK/WkbSk1tiL9osLiazPrYMNBLlm0AE76n04ArO/athMs4LIQtigoxo4gcoEMWjzCtEIO X-Received: by 2002:a17:90a:948c:b0:296:f9f:9d77 with SMTP id s12-20020a17090a948c00b002960f9f9d77mr137240pjo.30.1707239370737; Tue, 06 Feb 2024 09:09:30 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707239370; cv=pass; d=google.com; s=arc-20160816; b=Y86eKFWOSItJwZ9fUqRe8v6kzZh26Hnf7pGi2jPUWIGhwD9o4guY5aShojfpDa06d6 /z1sKf7M38DRSkYJsOjpRfaw+3nNoGWdOcxRHGAww2rsx+vt4uNhw2+pnoAUM3QfQh62 KOnHTVtwfz4nX8ApLa3wXbWB9gJHEO3+wLR4A+ufDS+mzZPhdZOWsHKMJKEUQSP2vqwQ dEkhSW7O2vF+/sodvJbmVMHNB99weziSY3DqORepoCj1aLZoFU90sZzPSGjUNeWpxqiH ecOpIDAe/9Xo4FLqUjwTj3b1ug9S2jwjLkcYUzF37XiHdjolCYq07k57IggNMydnU2PH Hi2Q== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:date:subject:cc:to:from :message-id:dkim-signature; bh=nq8N3iJKzTg/aO9s2k31bxowdIKIrZYsvIlCVzu6Hsk=; fh=8m6BmRPkPr86R13Gf0r6B4ezouk5MLIlo61tNsY9FEM=; b=0oaTqs2pE8dW5mpMQ2Aqu/H/am8hahSE1kewC85AsTBx3fiyQ0Wk3JcH7JSCsPD2Qw KYBXx/nN9utGyogLmmBDxMK/gTv1soXej47cGcq6PNtDfOColiDZN65jzKCtxSxx03ca MmU565FwceZ/4J8PJjwYxGFsmQS3F2R+Rw9xgbXc4pKSNRjZQlF/c8NjplxMDU1OVoHK r63qKmoYWfWBQJpsbEYq+MY/cEsaB/wLJuagchuKcQ4i/f49CqBb7zBHDTb17kIRRTto T6AKHmZcrCQlxKkHFYn3lg1XD99HgH0GPVxbaThdGi/qjUV3TVgYusAuyCqo/XB1+vNz FZkg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@foxmail.com header.s=s201512 header.b=jJTGrxPM; arc=pass (i=1 spf=pass spfdomain=foxmail.com dkim=pass dkdomain=foxmail.com dmarc=pass fromdomain=foxmail.com); spf=pass (google.com: domain of linux-kernel+bounces-55328-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-55328-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=foxmail.com X-Forwarded-Encrypted: i=1; AJvYcCWGSAusHIQS3smoHu1TzTMHyPYoTMVT0x4TdNNlLhlCbRWJyzVrGqjOMt/zSvy6aVVlGgRwgooD2pmN7VPtGDuCWKlNcA== Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id ml10-20020a17090b360a00b0029651a4eb01si1403247pjb.46.2024.02.06.09.09.30 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Feb 2024 09:09:30 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-55328-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@foxmail.com header.s=s201512 header.b=jJTGrxPM; arc=pass (i=1 spf=pass spfdomain=foxmail.com dkim=pass dkdomain=foxmail.com dmarc=pass fromdomain=foxmail.com); spf=pass (google.com: domain of linux-kernel+bounces-55328-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-55328-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=foxmail.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id BE87CB26C39 for <ouuuleilei@gmail.com>; Tue, 6 Feb 2024 16:41:18 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 711D08F4E; Tue, 6 Feb 2024 16:40:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=foxmail.com header.i=@foxmail.com header.b="jJTGrxPM" Received: from out203-205-221-202.mail.qq.com (out203-205-221-202.mail.qq.com [203.205.221.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F26324A08; Tue, 6 Feb 2024 16:40:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=203.205.221.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707237653; cv=none; b=TQR4XQJx3dxJ5hfC8Si61oHeh0fyw1f9YcuTPxk4qlAbxArD/Gak2187kf+6oKF1sLe/QMlOISBcesPcsLXA7DQUwxvRr/1MXHjAIp2x+zdJ8PxKgwdTCEJoOVL3NvoZmDVlzshV7q/6wSWLMiaWFrgh+R9EymHg8cUbk7fZBKA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707237653; c=relaxed/simple; bh=1TTnethT9ACWbE+2/u7LuqUNvlepRYWJQLWF5PV4eVo=; h=Message-ID:From:To:Cc:Subject:Date:MIME-Version; b=rXAXcGKewsNXlLq6YeFIesywAd2x+MBX4+5YKsFVeCMGFkm0PuaiOMED4gIgcZ192NRp89ozHpUG1mRS/vbniLKlk3ujJ3YM5Xjj3NzDT+gXxciK7PPqTnIFiwHOSZwkd3sqK1eTNSfLiogMtwfQYeBtJvNQi97qxW/32dNpoKY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=foxmail.com; spf=pass smtp.mailfrom=foxmail.com; dkim=pass (1024-bit key) header.d=foxmail.com header.i=@foxmail.com header.b=jJTGrxPM; arc=none smtp.client-ip=203.205.221.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=foxmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=foxmail.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foxmail.com; s=s201512; t=1707237338; bh=nq8N3iJKzTg/aO9s2k31bxowdIKIrZYsvIlCVzu6Hsk=; h=From:To:Cc:Subject:Date; b=jJTGrxPMkWKgIPx/Lt8hzE0b+hk0gRCHObtmBodsyn5bkf/rJeeG0tEishDin6CpU 0BsL+oHt/WwJBjDWUmOeQoDm+/Nk1HbQ2FrIyAcE5enoPDnUKemO7etI9aJZQTAcOp mNF8GkGva/BL73BWBifepzsVsU8g99II1JPiIUK0= Received: from localhost.localdomain ([2409:8962:5b2:1ce9:ee76:89e4:5983:4db0]) by newxmesmtplogicsvrszc5-0.qq.com (NewEsmtp) with SMTP id 8E113278; Wed, 07 Feb 2024 00:35:33 +0800 X-QQ-mid: xmsmtpt1707237333tgwzpj2kr Message-ID: <tencent_10AAA44731FFFA493F9F5501521F07DD4D0A@qq.com> X-QQ-XMAILINFO: NKv2G1wnhDBn0Qeh0KEAELRU5PYymkJtjrJl0x9WPh7uY2FwQzhHGIHIUWLC+F 9FTchisw4zfIsnJod27XT91951dwj1nw8gua0iYpm6z0susMJjdrMtjZZ380LYrjlX+wNkPNlwde TQTebx3ih0f7TTayCpVB7ENm9xf9Ki0WaEUxp7YRYSjQavgepJwA2JnHxoDAKDgk0eKPZ/JNqv9G CR7ShxvokbDpzgW+VokAJiZXd1nM8JovPS0kKNJpS5Z4Z/cSi7EhwYBAjH5am2NV3af9BtaCO66W Qi8N5E6gjB1esSulFhp2DI/hxozXirRN1mItweYx/XMhH+QWPFiiPWeck/wFORWpriUNw0vzYgG5 r5vcQemzDaAZ5bUW5Q0ae1rPpTXxyU+wi+Q1YF8+cB08622la1N3exP8lA+Am6jkBQ5+R8t1/zgt Yr4eVxROlPP9bimPPbxciyq2/pLLX8xJDKxervzmf9IIq1UDWQV/Kgw0ua9BuDqaldOL8MikkCQw x8Op2sQfD97ORuELvNyL95EdMAmfz5bKvCEJDeeH8Zh1agCqXhunlmfQbBHi2KjlrEHP7+s1jx+G 08K8b27J2cOqszbAYygspb1E3z+zQW2pNgtcr7k1hvjFAkbvCNN3T9bNd2R4m7jgSkIf9+6mzayT 0TSstqJusKSZ04oc3V6N1kI+4SZ5jhykzHX4wVRoVuxE5RP9hG9Xqa2IwFIv55Dx/7YJKLC5F5l5 im5iVya06TUKbVd44+DkEYyD8mUZV6Hnmha3A9n63ZR5LwTINrg5EMyzzka1kPS/WL2/2N0nAJ1r g+WjIT6jPeTiVi3Cb0lZPh2AB/Uxad7X3ePSmCd+I6BFX+qOUMyV6N3vm1pYpdG0U+geAvMXAziu 88jC5oa8XQRL+NAUsfUnciGliz+W5x+tP/SzPQ5q5ye2xudAAnriscZhHdUa9qSKypxtQcH/2njb gq2nVhigbnxNUSH8Rf1JhVyDRTUaVWmy4Kiflf9IarASsirh88Fi9BCsFzAfEgYCfyHn6lzFoWGj /JgsXFqZAMK1IX9+o6JTAu5hNlXCcHQ0lypBVY3w== X-QQ-XMRINFO: Nq+8W0+stu50PRdwbJxPCL0= From: wenyang.linux@foxmail.com To: Christian Brauner <brauner@kernel.org>, Jens Axboe <axboe@kernel.dk>, Alexander Viro <viro@zeniv.linux.org.uk> Cc: Wen Yang <wenyang.linux@foxmail.com>, Jan Kara <jack@suse.cz>, David Woodhouse <dwmw@amazon.co.uk>, Matthew Wilcox <willy@infradead.org>, Eric Biggers <ebiggers@google.com>, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] eventfd: strictly check the count parameter of eventfd_write to avoid inputting illegal strings Date: Wed, 7 Feb 2024 00:35:18 +0800 X-OQ-MSGID: <20240206163518.3811-1-wenyang.linux@foxmail.com> X-Mailer: git-send-email 2.25.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790170230199334312 X-GMAIL-MSGID: 1790170230199334312 |
Series |
eventfd: strictly check the count parameter of eventfd_write to avoid inputting illegal strings
|
|
Commit Message
Wen Yang
Feb. 6, 2024, 4:35 p.m. UTC
From: Wen Yang <wenyang.linux@foxmail.com> Since eventfd's document has clearly stated: A write(2) call adds the 8-byte integer value supplied in its buffer to the counter. However, in the current implementation, the following code snippet did not cause an error: char str[16] = "hello world"; uint64_t value; ssize_t size; int fd; fd = eventfd(0, 0); size = write(fd, &str, strlen(str)); printf("eventfd: test writing a string, size=%ld\n", size); size = read(fd, &value, sizeof(value)); printf("eventfd: test reading as uint64, size=%ld, valus=0x%lX\n", size, value); close(fd); And its output is: eventfd: test writing a string, size=8 eventfd: test reading as uint64, size=8, valus=0x6F77206F6C6C6568 By checking whether count is equal to sizeof(ucnt), such errors could be detected. It also follows the requirements of the manual. Signed-off-by: Wen Yang <wenyang.linux@foxmail.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Jens Axboe <axboe@kernel.dk> Cc: Christian Brauner <brauner@kernel.org> Cc: Jan Kara <jack@suse.cz> Cc: David Woodhouse <dwmw@amazon.co.uk> Cc: Matthew Wilcox <willy@infradead.org> Cc: Eric Biggers <ebiggers@google.com> Cc: <linux-fsdevel@vger.kernel.org> Cc: <linux-kernel@vger.kernel.org> --- fs/eventfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Comments
On Wed, 07 Feb 2024 00:35:18 +0800, wenyang.linux@foxmail.com wrote: > Since eventfd's document has clearly stated: A write(2) call adds > the 8-byte integer value supplied in its buffer to the counter. > > However, in the current implementation, the following code snippet > did not cause an error: > > char str[16] = "hello world"; > uint64_t value; > ssize_t size; > int fd; > > [...] Applied to the vfs.misc branch of the vfs/vfs.git tree. Patches in the vfs.misc branch should appear in linux-next soon. Please report any outstanding bugs that were missed during review in a new review to the original patch series allowing us to drop it. It's encouraged to provide Acked-bys and Reviewed-bys even though the patch has now been applied. If possible patch trailers will be updated. Note that commit hashes shown below are subject to change due to rebase, trailer updates or similar. If in doubt, please check the listed branch. tree: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git branch: vfs.misc [1/1] eventfd: strictly check the count parameter of eventfd_write to avoid inputting illegal strings https://git.kernel.org/vfs/vfs/c/325e56e9236e
On Wed, Feb 07, 2024 at 12:35:18AM +0800, wenyang.linux@foxmail.com wrote: > From: Wen Yang <wenyang.linux@foxmail.com> > > Since eventfd's document has clearly stated: A write(2) call adds > the 8-byte integer value supplied in its buffer to the counter. > > However, in the current implementation, the following code snippet > did not cause an error: > > char str[16] = "hello world"; > uint64_t value; > ssize_t size; > int fd; > > fd = eventfd(0, 0); > size = write(fd, &str, strlen(str)); > printf("eventfd: test writing a string, size=%ld\n", size); > size = read(fd, &value, sizeof(value)); > printf("eventfd: test reading as uint64, size=%ld, valus=0x%lX\n", > size, value); > > close(fd); > > And its output is: > eventfd: test writing a string, size=8 > eventfd: test reading as uint64, size=8, valus=0x6F77206F6C6C6568 > > By checking whether count is equal to sizeof(ucnt), such errors > could be detected. It also follows the requirements of the manual. > > Signed-off-by: Wen Yang <wenyang.linux@foxmail.com> > Cc: Alexander Viro <viro@zeniv.linux.org.uk> > Cc: Jens Axboe <axboe@kernel.dk> > Cc: Christian Brauner <brauner@kernel.org> > Cc: Jan Kara <jack@suse.cz> > Cc: David Woodhouse <dwmw@amazon.co.uk> > Cc: Matthew Wilcox <willy@infradead.org> > Cc: Eric Biggers <ebiggers@google.com> > Cc: <linux-fsdevel@vger.kernel.org> > Cc: <linux-kernel@vger.kernel.org> > --- Seems sensible but has the potential to break users that rely on this but then again glibc already enforces a 64bit value via eventfd_write() and eventfd_read().
On Wed, Feb 07, 2024 at 12:35:18AM +0800, wenyang.linux@foxmail.com wrote: > By checking whether count is equal to sizeof(ucnt), such errors > could be detected. It also follows the requirements of the manual. Does it? This is what the eventfd manual page says: A write(2) fails with the error EINVAL if the size of the supplied buffer is less than 8 bytes, or if an attempt is made to write the value 0xffffffffffffffff. So, *technically* it doesn't mention the behavior if the size is greater than 8 bytes. But one might assume that such writes are accepted, since otherwise it would have been mentioned that they're rejected, just like writes < 8 bytes. If the validation is indeed going to be made more strict, the manual page will need to be fixed alongside it. - Eric
On 2024/2/8 12:33, Eric Biggers wrote: > On Wed, Feb 07, 2024 at 12:35:18AM +0800, wenyang.linux@foxmail.com wrote: >> By checking whether count is equal to sizeof(ucnt), such errors >> could be detected. It also follows the requirements of the manual. > Does it? This is what the eventfd manual page says: > > A write(2) fails with the error EINVAL if the size of the supplied buffer > is less than 8 bytes, or if an attempt is made to write the value > 0xffffffffffffffff. > > So, *technically* it doesn't mention the behavior if the size is greater than 8 > bytes. But one might assume that such writes are accepted, since otherwise it > would have been mentioned that they're rejected, just like writes < 8 bytes. Thank you for your commtents. Although this behavior was not mentioned, it may indeed lead to undefined performance, such as (we changed char [] to char *): #include <sys/eventfd.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> int main() { //char str[32] = "hello world"; char *str = "hello world"; uint64_t value; ssize_t size; int fd; fd = eventfd(0, 0); size = write(fd, &str, strlen(str)); printf("eventfd: test writing a string:%s, size=%ld\n", str, size); size = read(fd, &value, sizeof(value)); printf("eventfd: test reading as uint64, size=%ld, value=0x%lX\n", size, value); close(fd); return 0; } $ ./a.out eventfd: test writing a string:hello world, size=8 eventfd: test reading as uint64, size=8, value=0x560CC0134008 $ ./a.out eventfd: test writing a string:hello world, size=8 eventfd: test reading as uint64, size=8, value=0x55A3CD373008 $ ./a.out eventfd: test writing a string:hello world, size=8 eventfd: test reading as uint64, size=8, value=0x55B8D7B99008 -- Best wishes, Wen > > If the validation is indeed going to be made more strict, the manual page will > need to be fixed alongside it. > > - Eric
On Wed, Feb 07, 2024 at 08:33:54PM -0800, Eric Biggers wrote: > On Wed, Feb 07, 2024 at 12:35:18AM +0800, wenyang.linux@foxmail.com wrote: > > By checking whether count is equal to sizeof(ucnt), such errors > > could be detected. It also follows the requirements of the manual. > > Does it? This is what the eventfd manual page says: > > A write(2) fails with the error EINVAL if the size of the supplied buffer > is less than 8 bytes, or if an attempt is made to write the value > 0xffffffffffffffff. > > So, *technically* it doesn't mention the behavior if the size is greater than 8 > bytes. But one might assume that such writes are accepted, since otherwise it > would have been mentioned that they're rejected, just like writes < 8 bytes. > > If the validation is indeed going to be made more strict, the manual page will > need to be fixed alongside it. Do you prefer we drop this patch?
diff --git a/fs/eventfd.c b/fs/eventfd.c index fc4d81090763..9afdb722fa92 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c @@ -251,7 +251,7 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c ssize_t res; __u64 ucnt; - if (count < sizeof(ucnt)) + if (count != sizeof(ucnt)) return -EINVAL; if (copy_from_user(&ucnt, buf, sizeof(ucnt))) return -EFAULT;