commit 79df5edad678f1cca01da8875f4f7b7f2d9ca705 from: Stefan Sperling date: Tue Sep 17 09:47:28 2024 UTC make the rtable command actually update the rtable of the nsh process The assumption that nsh always runs in rdomain 0 is invalid. Stop assuming that cli_rtable is set to zero by default, and switch the nsh process rdomain accordingly as needed. commit - f7111bee0697dc42252d3d381f4643b9aeca6431 commit + 79df5edad678f1cca01da8875f4f7b7f2d9ca705 blob - 1ad626d1e540c3787254cd0354cbbc1b1c6f3fde blob + beb254bed60bf5c22b8d262e8454bfbbf041d3e7 --- cmdargs.c +++ cmdargs.c @@ -89,7 +89,7 @@ cmdargs_output_setenv(char *cmd, char *arg[], int stdo signal(SIGINT, SIG_DFL); signal(SIGCHLD, SIG_DFL); - if (cli_rtable != 0 && nsh_setrtable(cli_rtable)) + if (nsh_setrtable(cli_rtable)) _exit(0); if (stdoutfd != -1) { @@ -178,7 +178,7 @@ nsh_setrtable(int rtableid) cli_rtable); break; case EPERM: - printf("%% nsh not running as root?\n"); + printf("%% Privileged required\n"); break; default: printf("%% setrtable failed: %d\n", errno); blob - df306ef7cdbb171166b7cc977fc67695a9f82c5e blob + 0dc92dac58e59ec9fb01a7e0e79966ded6640949 --- commands.c +++ commands.c @@ -1465,11 +1465,25 @@ interface(int argc, char **argv, char *modhvar) printf("%% Invalid command\n"); } else { int save_cli_rtable = cli_rtable; - cli_rtable = 0; + + /* + * Run the handler in the default routing domain. + * This requires privileged mode if we are not + * already in rdomain 0. + */ + if (getrtable() != 0 && !priv) { + printf("%% Privilege required\n"); + return (0); + } + if (cli_rtable != 0 && nsh_setrtable(0) == 0) + cli_rtable = 0; + ((*i->handler) (ifname, ifs, argc, argv)); - cli_rtable = save_cli_rtable; + if (save_cli_rtable != cli_rtable && + nsh_setrtable(cli_rtable) == 0) + cli_rtable = save_cli_rtable; } ifname[0] = '\0'; @@ -1532,13 +1546,29 @@ interface(int argc, char **argv, char *modhvar) printf("%% Invalid command\n"); } else { int save_cli_rtable = cli_rtable; - cli_rtable = 0; + int ret; - if ((*i->handler) (ifname, ifs, margc, margv)) { + /* + * Run the handler in the default routing domain. + * This requires privileged mode if we are not + * already in rdomain 0. + */ + if (getrtable() != 0 && !priv) { + printf("%% Privilege required\n"); + return (0); + } + + if (cli_rtable != 0 && nsh_setrtable(0) == 0) + cli_rtable = 0; + + ret = (*i->handler) (ifname, ifs, margc, margv); + + if (cli_rtable != save_cli_rtable && + nsh_setrtable(cli_rtable) == 0) cli_rtable = save_cli_rtable; + + if (ret) break; - } - cli_rtable = save_cli_rtable; } if (i && i->handler == int_interface && next_ifname[0] != '\0' && @@ -2298,11 +2328,25 @@ docmd(int argc, char **argv) printf("%% Invalid command\n"); } else { int save_cli_rtable = cli_rtable; - cli_rtable = 0; + /* + * Run the handler in the default routing domain. + * This requires privileged mode if we are not + * already in rdomain 0. + */ + if (getrtable() != 0 && !priv) { + printf("%% Privilege required\n"); + return 0; + } + + if (cli_rtable != 0 && nsh_setrtable(cli_rtable) == 0) + cli_rtable = 0; + ((*i->handler) (ifname, ifs, argc, argv)); - cli_rtable = save_cli_rtable; + if (save_cli_rtable != cli_rtable && + nsh_setrtable(cli_rtable) == 0) + cli_rtable = save_cli_rtable; } close(ifs); } else { @@ -2652,7 +2696,7 @@ argvtostring(int argc, char **argv, char *string, int int rtable(int argc, char **argv) { - int table, set, pos, found; + int table, set, pos, found, curtable; const char *errstr; char rtname[64]; StringList *resp; @@ -2682,6 +2726,23 @@ rtable(int argc, char **argv) return 1; } + curtable = getrtable(); + if (cli_rtable != curtable) { + printf("%% WARNING: nsh process rtable is out of sync " + "(want %d, have %d); " + "This is probably a bug in nsh, please report it.\n", + cli_rtable, curtable); + } + + /* + * The kernel will prevent unprivileged users from switching + * away from rdomains other than 0. + */ + if (set && !priv && cli_rtable != 0 && cli_rtable != table) { + printf("%% Privilege required\n"); + return 1; + } + argc -= 2; argv += 2; @@ -2705,7 +2766,13 @@ rtable(int argc, char **argv) } if (set && (found && !pos)) { + if (!priv && cli_rtable != 0) { + printf("%% Privilege required\n"); + return 1; + } /* Table found, skip database action */ + if (nsh_setrtable(table)) + return 1; cli_rtable = table; return 0; } @@ -2720,6 +2787,8 @@ rtable(int argc, char **argv) } } else if (table == 0) { /* Do not add the kernel's default rtable 0 to the database. */ + if (nsh_setrtable(0)) + return 1; cli_rtable = 0; return 0; } @@ -2732,8 +2801,12 @@ rtable(int argc, char **argv) printf("%% rtable db insertion error\n"); return 1; } + if (nsh_setrtable(table)) + return 1; cli_rtable = table; } else { + if (nsh_setrtable(0)) + return 1; cli_rtable = 0; }