Received: by 2002:a05:6358:489b:b0:bb:da1:e618 with SMTP id x27csp983244rwn; Thu, 8 Sep 2022 11:29:11 -0700 (PDT) X-Google-Smtp-Source: AA6agR6kimHh1kEJ8lJ8f4TBUR7i+vw5KRAKApJJyU97EULDL8gipeQ0iCf4ICUUdgrjqMWg8WhA X-Received: by 2002:a05:6512:22c1:b0:498:f1f1:1421 with SMTP id g1-20020a05651222c100b00498f1f11421mr966704lfu.389.1662661750749; Thu, 08 Sep 2022 11:29:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1662661750; cv=none; d=google.com; s=arc-20160816; b=jloOna/aADwPWgNhEDkQiE1d0C0bxjohnnB98+3KYV8krA9Qjk/9zyJFFIPncN0T1M k/7w3SI66t+xontpJlS47skrP+7Isg1534MlN1O5SXYpNLtFFAf+NUw+9rWTnZapx6Hr iJAueU+qct6CNfM0ylnb10y/EejtakIvZS+PLzc4zrSdjiBc/LZObEpUpt1ZLS2LM5oi f1dDyn6L29Vkg52B1wwb/Y0bpzxNImTIR4M+lRoy0HgrgIh0NKxlHuTiEE3A0+hZ/GS1 0EfB4EPTcoyKzOtBR9gZXZpAZMsZhkmeFAVzYAT80Ou9ZRxE5mAyH34XRkwOIbrkYroW Kjbw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-disposition:mime-version:message-id :subject:cc:to:from:date:dkim-signature; bh=0qMQLVEVJZBmgN+4OndfYCHKMuf7l9KBNcONt34CdKc=; b=Faid2ElKmWak96GKGFABqnwbko+RZAFjYyavm3ucxId2Yf4sp7WbkXje5IacoixhrB WLFRx7iRsPALYlenRRtOnlp8L6zCZ8WTejYKqglCYs8hB91dZlw7VCBa0y4FxiY7jLI3 0KL5aeHYYQ1S9216lbYyTdVl2jJikxmepNQkx177ZAm1XEv3qZDg7i1T/hj/fxldbPUV I3Cv9X7QpD/oeaRD2/ABe/Dr6dTpBPZeqpg1CwPdvARf4EPVmr8i+6xYD82IUq9tg3Du HNFMQEcZY/KLdlZPJwIrqP+72aJyVAfUOkceDp5JUiRZdhzB+STtGR4ZrUGEfMZjUJ9j jJxw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=GcZoTl2b; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bp13-20020a056512158d00b00497e864d925si1644369lfb.45.2022.09.08.11.28.40; Thu, 08 Sep 2022 11:29:10 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=GcZoTl2b; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231866AbiIHSWD (ORCPT + 99 others); Thu, 8 Sep 2022 14:22:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58832 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231251AbiIHSWA (ORCPT ); Thu, 8 Sep 2022 14:22:00 -0400 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0CC4EEB855; Thu, 8 Sep 2022 11:21:59 -0700 (PDT) Received: by mail-wr1-x42e.google.com with SMTP id t14so20271096wrx.8; Thu, 08 Sep 2022 11:21:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-disposition:mime-version:message-id:subject:cc:to:from:date :from:to:cc:subject:date; bh=0qMQLVEVJZBmgN+4OndfYCHKMuf7l9KBNcONt34CdKc=; b=GcZoTl2bCRlFzOoz5mrR7kWHp6+udvfQfj1QwcUqbtCRz/DA8W+t8Al/tF2lbjU4JW YqG6M9K63oE09s+sPMnVBIWAHX4ldXqlmA9f6TyzzTW8yYK8lX5LXE8EtxFin8xYiaLA Q+cxyy89dgx7Zapzjgub6gTZWG1DqCqOZ8bBxzZepzOv1GJ+PqEJQAKkcTFJs3t/cQkz jo0l0wFSXXZLMb8Pr/WJ8XEz/esYSRt1VQWZLLCOmjK/UkoptIN+MAXtAYbfHbK1TmcD g5Lx8cGpVvd/nQOkNmAUawBsbRxre3OxOUKsEq9EZG5pXpwkxDOilKIAJ4x3BbmdvRaL /Vsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-disposition:mime-version:message-id:subject:cc:to:from:date :x-gm-message-state:from:to:cc:subject:date; bh=0qMQLVEVJZBmgN+4OndfYCHKMuf7l9KBNcONt34CdKc=; b=VZmMNUCf2K8447qdDaqYvGOg++oAdNOP72cDEnBI1X3Ob9Qa7rH9yV8Sy6fTBH8hYj w7QZALzoyyCIytLxldVFl2usfYnZrqPVIB0hJBD9ownJiNsKUITYfHYdjT5nvOwcR8UX ydj0QeyVnt/bjWAmGYUSKGwACLjVpjMJdTGU/Urm6t3zwDCFKWeAUeEaH02gmcluulQw WDTT++S+7a3cve11JhGlx3dYEfjNCK1NLu8Id5FAn1e90evU26CBBMmDuPaTUbhPdwaQ kR6Tj5971NO1Bxwjr7FzT/Qiz8wMH1Xu8yczmrvgZLoMJWW6y22I9pqJtyYQjwx8HJtS fNUw== X-Gm-Message-State: ACgBeo0WJC03BfIahgHRlHe1df5PpsA0zf8/As/P0dECpk//iPc1J3sM vQfPwpz8XdKv9Up5TdxknPLy58NzfA== X-Received: by 2002:a05:6000:1706:b0:22a:2c1d:f578 with SMTP id n6-20020a056000170600b0022a2c1df578mr3230336wrc.236.1662661317193; Thu, 08 Sep 2022 11:21:57 -0700 (PDT) Received: from localhost.localdomain ([46.53.251.11]) by smtp.gmail.com with ESMTPSA id m29-20020a05600c3b1d00b003a845fa1edfsm10465228wms.3.2022.09.08.11.21.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Sep 2022 11:21:56 -0700 (PDT) Date: Thu, 8 Sep 2022 21:21:54 +0300 From: Alexey Dobriyan To: akpm@linux-foundation.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH] proc: give /proc/cmdline size Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Most /proc files don't have length (in fstat sense). This leads to inefficiencies when reading such files with APIs commonly found in modern programming languages. They open file, then fstat descriptor, get st_size == 0 and either assume file is empty or start reading without knowing target size. cat(1) does OK because it uses large enough buffer by default. But naive programs copy-pasted from SO aren't: let mut f = std::fs::File::open("/proc/cmdline").unwrap(); let mut buf: Vec = Vec::new(); f.read_to_end(&mut buf).unwrap(); will result in openat(AT_FDCWD, "/proc/cmdline", O_RDONLY|O_CLOEXEC) = 3 statx(0, NULL, AT_STATX_SYNC_AS_STAT, STATX_ALL, NULL) = -1 EFAULT (Bad address) statx(3, "", AT_STATX_SYNC_AS_STAT|AT_EMPTY_PATH, STATX_ALL, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID, stx_attributes=0, stx_mode=S_IFREG|0444, stx_size=0, ...}) = 0 lseek(3, 0, SEEK_CUR) = 0 read(3, "BOOT_IMAGE=(hd3,gpt2)/vmlinuz-5.", 32) = 32 read(3, "19.6-100.fc35.x86_64 root=/dev/m", 32) = 32 read(3, "apper/fedora_localhost--live-roo"..., 64) = 64 read(3, "ocalhost--live-swap rd.lvm.lv=fe"..., 128) = 116 read(3, "", 12) open/stat is OK, lseek looks silly but there are 3 unnecessary reads because Rust starts with 32 bytes per Vec and grows from there. In case of /proc/cmdline, the length is known precisely. Make variables readonly while I'm at it. P.S.: I tried to scp /proc/cpuinfo today and got empty file but this is separate story. Signed-off-by: Alexey Dobriyan --- fs/proc/cmdline.c | 6 +++++- include/linux/init.h | 1 + init/main.c | 7 +++++-- 3 files changed, 11 insertions(+), 3 deletions(-) --- a/fs/proc/cmdline.c +++ b/fs/proc/cmdline.c @@ -3,6 +3,7 @@ #include #include #include +#include "internal.h" static int cmdline_proc_show(struct seq_file *m, void *v) { @@ -13,7 +14,10 @@ static int cmdline_proc_show(struct seq_file *m, void *v) static int __init proc_cmdline_init(void) { - proc_create_single("cmdline", 0, NULL, cmdline_proc_show); + struct proc_dir_entry *pde; + + pde = proc_create_single("cmdline", 0, NULL, cmdline_proc_show); + pde->size = saved_command_line_len + 1; return 0; } fs_initcall(proc_cmdline_init); --- a/include/linux/init.h +++ b/include/linux/init.h @@ -143,6 +143,7 @@ struct file_system_type; extern int do_one_initcall(initcall_t fn); extern char __initdata boot_command_line[]; extern char *saved_command_line; +extern unsigned int saved_command_line_len; extern unsigned int reset_devices; /* used by init/main.c */ --- a/init/main.c +++ b/init/main.c @@ -143,7 +143,8 @@ void (*__initdata late_time_init)(void); /* Untouched command line saved by arch-specific code. */ char __initdata boot_command_line[COMMAND_LINE_SIZE]; /* Untouched saved command line (eg. for /proc) */ -char *saved_command_line; +char *saved_command_line __ro_after_init; +unsigned int saved_command_line_len __ro_after_init; /* Command line for parameter parsing */ static char *static_command_line; /* Untouched extra command line */ @@ -665,6 +666,8 @@ static void __init setup_command_line(char *command_line) strcpy(saved_command_line + len, extra_init_args); } } + + saved_command_line_len = strlen(saved_command_line); } /* @@ -1372,7 +1375,7 @@ static void __init do_initcall_level(int level, char *command_line) static void __init do_initcalls(void) { int level; - size_t len = strlen(saved_command_line) + 1; + size_t len = saved_command_line_len + 1; char *command_line; command_line = kzalloc(len, GFP_KERNEL);