From: cgoesche Date: Sun, 2 Nov 2025 16:55:09 +0000 (-0500) Subject: su: pass arguments after to shell X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ac0147fd14b348097c82c1c89a5417b582e26bad;p=thirdparty%2Futil-linux.git 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 --- 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; }