The su(1) manpage describes how the arguments after <user>
are passed to the invoked shell. However this is empirically
wrong, as option flags after <user> 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 '<user>'.
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 <cgoesc2@wgu.edu>
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);
}
FALLTHROUGH;
case SU_MODE:
- if (optind < argc)
+ if (optind < argc && *argv[optind] != '-')
su->new_user = argv[optind++];
break;
}