From ac0147fd14b348097c82c1c89a5417b582e26bad Mon Sep 17 00:00:00 2001 From: cgoesche Date: Sun, 2 Nov 2025 11:55:09 -0500 Subject: [PATCH] su: pass arguments after to shell The su(1) manpage describes how the arguments after are passed to the invoked shell. However this is empirically wrong, as option flags after are interpreted by su(1) and will eventually never be passed or yield an error that terminates the program due to an unrecognized option flag. To fix this we can change getopt(3)'s scanning mode with a '+' prefixed to 'optstring', this will make it so that getopt(3) stops processing argv elements on the first occurrence of a non-option argument, e.g. '-' or ''. Additionally, if the argument that directly follows '-' is an option flag, su(1) will assume that this argument and the ones that follow, are to be passed to a shell invoked by the root user. Addresses: https://github.com/util-linux/util-linux/pull/1809 Signed-off-by: cgoesche --- login-utils/su-common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/login-utils/su-common.c b/login-utils/su-common.c index 38d476a1a..4d54eab31 100644 --- a/login-utils/su-common.c +++ b/login-utils/su-common.c @@ -1036,7 +1036,7 @@ int su_main(int argc, char **argv, int mode) su->conv.appdata_ptr = (void *) su; while ((optc = - getopt_long(argc, argv, "c:fg:G:lmpPTs:u:hVw:", longopts, + getopt_long(argc, argv, "+c:fg:G:lmpPTs:u:hVw:", longopts, NULL)) != -1) { err_exclusive_options(optc, longopts, excl, excl_st); @@ -1142,7 +1142,7 @@ int su_main(int argc, char **argv, int mode) } FALLTHROUGH; case SU_MODE: - if (optind < argc) + if (optind < argc && *argv[optind] != '-') su->new_user = argv[optind++]; break; } -- 2.47.3