| 1 | Submitted By: Jim Gifford (jim at cross-lfs dot org) |
| 2 | Date: 01-07-2008 |
| 3 | Initial Package Version: 2.86 |
| 4 | Origin: Various |
| 5 | Upstream Status: Unknown |
| 6 | Description: Fixes to Major issues in Sysvinit -- listed Below |
| 7 | IPV6 Displayed Incorrectly |
| 8 | On 64bit which have 32bit multilib support, the utmp struct is the same |
| 9 | Fix bug where proc names are truncated |
| 10 | Fixed support for POSIX capabilite |
| 11 | All halt/reboot to handle being called by login correctly |
| 12 | Preserve waiting state across re-exec |
| 13 | Allow failed console opens some time to resolve themselves |
| 14 | |
| 15 | New: |
| 16 | Added kexec support |
| 17 | |
| 18 | diff -Naur sysvinit-2.86.orig/man/halt.8 sysvinit-2.86/man/halt.8 |
| 19 | --- sysvinit-2.86.orig/man/halt.8 2001-11-21 13:11:22.000000000 -0800 |
| 20 | +++ sysvinit-2.86/man/halt.8 2009-01-07 11:07:06.000000000 -0800 |
| 21 | @@ -23,6 +23,7 @@ |
| 22 | .RB [ \-d ] |
| 23 | .RB [ \-f ] |
| 24 | .RB [ \-i ] |
| 25 | +.RB [ \-k ] |
| 26 | .br |
| 27 | .B /sbin/poweroff |
| 28 | .RB [ \-n ] |
| 29 | @@ -65,6 +66,8 @@ |
| 30 | .IP \fB\-p\fP |
| 31 | When halting the system, do a poweroff. This is the default when halt is |
| 32 | called as \fBpoweroff\fP. |
| 33 | +.IP \fB\-k\fP |
| 34 | +Try to reboot using \fBkexec\fP, if kernel supports it. |
| 35 | .\"}}} |
| 36 | .\"{{{ Diagnostics |
| 37 | .SH DIAGNOSTICS |
| 38 | diff -Naur sysvinit-2.86.orig/man/init.8 sysvinit-2.86/man/init.8 |
| 39 | --- sysvinit-2.86.orig/man/init.8 2004-07-29 04:21:31.000000000 -0700 |
| 40 | +++ sysvinit-2.86/man/init.8 2009-01-07 11:23:45.000000000 -0800 |
| 41 | @@ -64,7 +64,7 @@ |
| 42 | .PP |
| 43 | Runlevel \fBS\fP or \fBs\fP bring the system to single user mode |
| 44 | and do not require an \fB/etc/inittab\fP file. In single user mode, |
| 45 | -\fB/sbin/sulogin\fP is invoked on \fB/dev/console\fP. |
| 46 | +a root shell is opened on \fB/dev/console\fP. |
| 47 | .PP |
| 48 | When entering single user mode, \fBinit\fP initializes the consoles |
| 49 | \fBstty\fP settings to sane values. Clocal mode is set. Hardware |
| 50 | diff -Naur sysvinit-2.86.orig/man/last.1 sysvinit-2.86/man/last.1 |
| 51 | --- sysvinit-2.86.orig/man/last.1 2004-07-30 04:39:18.000000000 -0700 |
| 52 | +++ sysvinit-2.86/man/last.1 2009-01-07 11:23:45.000000000 -0800 |
| 53 | @@ -60,6 +60,8 @@ |
| 54 | useful, e.g., to determine easily who was logged in at a particular |
| 55 | time -- specify that time with \fB\-t\fP and look for "still logged |
| 56 | in". |
| 57 | +.IP "\fB\-f\fP \fIfile\fP" |
| 58 | +Specifies a file to search other than \fB/var/log/wtmp\fP. |
| 59 | .IP \fB\-R\fP |
| 60 | Suppresses the display of the hostname field. |
| 61 | .IP \fB\-a\fP |
| 62 | diff -Naur sysvinit-2.86.orig/man/pidof.8 sysvinit-2.86/man/pidof.8 |
| 63 | --- sysvinit-2.86.orig/man/pidof.8 1998-09-02 05:49:33.000000000 -0700 |
| 64 | +++ sysvinit-2.86/man/pidof.8 2009-01-07 11:22:28.000000000 -0800 |
| 65 | @@ -4,6 +4,7 @@ |
| 66 | .SH SYNOPSIS |
| 67 | .B pidof |
| 68 | .RB [ \-s ] |
| 69 | +.RB [ \-c ] |
| 70 | .RB [ \-x ] |
| 71 | .RB [ \-o |
| 72 | .IR omitpid ] |
| 73 | @@ -24,6 +25,10 @@ |
| 74 | .SH OPTIONS |
| 75 | .IP -s |
| 76 | Single shot - this instructs the program to only return one \fIpid\fP. |
| 77 | +.IP -c |
| 78 | +Only return process ids that are running with the same root directory. |
| 79 | +This option is ignored for non-root users, as they will be unable to check |
| 80 | +the current root directory of processes they do not own. |
| 81 | .IP -x |
| 82 | Scripts too - this causes the program to also return process id's of |
| 83 | shells running the named scripts. |
| 84 | diff -Naur sysvinit-2.86.orig/man/shutdown.8 sysvinit-2.86/man/shutdown.8 |
| 85 | --- sysvinit-2.86.orig/man/shutdown.8 2004-06-09 05:47:45.000000000 -0700 |
| 86 | +++ sysvinit-2.86/man/shutdown.8 2009-01-07 11:08:22.000000000 -0800 |
| 87 | @@ -9,11 +9,11 @@ |
| 88 | .\"{{{ Synopsis |
| 89 | .SH SYNOPSIS |
| 90 | .B /sbin/shutdown |
| 91 | +.RB [ \-akrhPHfFnc ] |
| 92 | .RB [ \-t |
| 93 | .IR sec ] |
| 94 | -.RB [ \-arkhncfFHP ] |
| 95 | .I time |
| 96 | -.RI [ warning-message ] |
| 97 | +.RI [ "warning message" ] |
| 98 | .\"}}} |
| 99 | .\"{{{ Description |
| 100 | .SH DESCRIPTION |
| 101 | @@ -39,11 +39,6 @@ |
| 102 | .IP "\fB\-a\fP |
| 103 | Use \fB/etc/shutdown.allow\fP. |
| 104 | .\"}}} |
| 105 | -.\"{{{ -t sec |
| 106 | -.IP "\fB\-t\fP \fIsec\fP" |
| 107 | -Tell \fBinit\fP(8) to wait \fIsec\fP seconds between sending processes the |
| 108 | -warning and the kill signal, before changing to another runlevel. |
| 109 | -.\"}}} |
| 110 | .\"{{{ -k |
| 111 | .IP \fB\-k\fP |
| 112 | Don't really shutdown; only send the warning messages to everybody. |
| 113 | @@ -56,20 +51,14 @@ |
| 114 | .IP \fB\-h\fP |
| 115 | Halt or poweroff after shutdown. |
| 116 | .\"}}} |
| 117 | -.\"{{{ -H |
| 118 | -.IP \fB\-H\fP |
| 119 | -Halt action is to halt or drop into boot monitor on systems that |
| 120 | -support it. |
| 121 | -.\"}}} |
| 122 | .\"{{{ -P |
| 123 | .IP \fB\-P\fP |
| 124 | Halt action is to turn off the power. |
| 125 | .\"}}} |
| 126 | -.\"{{{ -n |
| 127 | -.IP \fB\-n\fP |
| 128 | -[DEPRECATED] Don't call \fBinit\fP(8) to do the shutdown but do it ourself. |
| 129 | -The use of this option is discouraged, and its results are not always what |
| 130 | -you'd expect. |
| 131 | +.\"{{{ -H |
| 132 | +.IP \fB\-H\fP |
| 133 | +Halt action is to halt or drop into boot monitor on systems that |
| 134 | +support it. |
| 135 | .\"}}} |
| 136 | .\"{{{ -f |
| 137 | .IP \fB\-f\fP |
| 138 | @@ -79,18 +68,29 @@ |
| 139 | .IP \fB\-F\fP |
| 140 | Force fsck on reboot. |
| 141 | .\"}}} |
| 142 | +.\"{{{ -n |
| 143 | +.IP \fB\-n\fP |
| 144 | +[DEPRECATED] Don't call \fBinit\fP(8) to do the shutdown but do it ourself. |
| 145 | +The use of this option is discouraged, and its results are not always what |
| 146 | +you'd expect. |
| 147 | +.\"}}} |
| 148 | .\"{{{ -c |
| 149 | .IP \fB\-c\fP |
| 150 | Cancel an already running shutdown. With this option it is of course |
| 151 | not possible to give the \fBtime\fP argument, but you can enter a |
| 152 | explanatory message on the command line that will be sent to all users. |
| 153 | .\"}}} |
| 154 | +.\"{{{ -t sec |
| 155 | +.IP "\fB\-t\fP \fIsec\fP" |
| 156 | +Tell \fBinit\fP(8) to wait \fIsec\fP seconds between sending processes the |
| 157 | +warning and the kill signal, before changing to another runlevel. |
| 158 | +.\"}}} |
| 159 | .\"{{{ time |
| 160 | .IP \fItime\fP |
| 161 | When to shutdown. |
| 162 | .\"}}} |
| 163 | .\"{{{ warning-message |
| 164 | -.IP \fIwarning-message\fP |
| 165 | +.IP "\fIwarning message\fP" |
| 166 | Message to send to all users. |
| 167 | .\"}}} |
| 168 | .PP |
| 169 | diff -Naur sysvinit-2.86.orig/man/sulogin.8 sysvinit-2.86/man/sulogin.8 |
| 170 | --- sysvinit-2.86.orig/man/sulogin.8 2004-06-09 05:47:45.000000000 -0700 |
| 171 | +++ sysvinit-2.86/man/sulogin.8 2009-01-07 11:23:45.000000000 -0800 |
| 172 | @@ -9,7 +9,7 @@ |
| 173 | .RB [ " tty-device " ] |
| 174 | .SH DESCRIPTION |
| 175 | .I sulogin |
| 176 | -is invoked by \fBinit(8)\fP when the system goes into single user mode |
| 177 | +can be invoked by \fBinit(8)\fP when the system goes into single user mode |
| 178 | (this is done through an entry in \fIinittab(5)\fP). \fBInit\fP also |
| 179 | tries to execute \fIsulogin\fP when it is passed the \fB-b\fP flag |
| 180 | from the bootmonitor (eg, LILO). |
| 181 | diff -Naur sysvinit-2.86.orig/src/bootlogd.c sysvinit-2.86/src/bootlogd.c |
| 182 | --- sysvinit-2.86.orig/src/bootlogd.c 2004-06-09 05:47:45.000000000 -0700 |
| 183 | +++ sysvinit-2.86/src/bootlogd.c 2009-01-07 11:34:12.000000000 -0800 |
| 184 | @@ -609,7 +609,7 @@ |
| 185 | else |
| 186 | todo = endptr - outptr; |
| 187 | if (fp && todo) |
| 188 | - writelog(fp, outptr, todo); |
| 189 | + writelog(fp, (unsigned char *)outptr, todo); |
| 190 | } |
| 191 | |
| 192 | if (fp) { |
| 193 | diff -Naur sysvinit-2.86.orig/src/halt.c sysvinit-2.86/src/halt.c |
| 194 | --- sysvinit-2.86.orig/src/halt.c 2004-07-30 05:16:18.000000000 -0700 |
| 195 | +++ sysvinit-2.86/src/halt.c 2009-01-07 11:25:19.000000000 -0800 |
| 196 | @@ -8,7 +8,7 @@ |
| 197 | * execute an "shutdown -r". This is for compatibility with |
| 198 | * sysvinit 2.4. |
| 199 | * |
| 200 | - * Usage: halt [-n] [-w] [-d] [-f] [-h] [-i] [-p] |
| 201 | + * Usage: halt [-n] [-w] [-d] [-f] [-h] [-i] [-p] [-k] |
| 202 | * -n: don't sync before halting the system |
| 203 | * -w: only write a wtmp reboot record and exit. |
| 204 | * -d: don't write a wtmp record. |
| 205 | @@ -16,6 +16,7 @@ |
| 206 | * -h: put harddisks in standby mode |
| 207 | * -i: shut down all network interfaces. |
| 208 | * -p: power down the system (if possible, otherwise halt). |
| 209 | + * -k: reboot the system using kexec. |
| 210 | * |
| 211 | * Reboot and halt are both this program. Reboot |
| 212 | * is just a link to halt. Invoking the program |
| 213 | @@ -64,8 +65,10 @@ |
| 214 | */ |
| 215 | void usage(void) |
| 216 | { |
| 217 | - fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-h] [-i]%s\n", |
| 218 | - progname, strcmp(progname, "halt") ? "" : " [-p]"); |
| 219 | + fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-h] [-i]%s%s\n", |
| 220 | + progname, |
| 221 | + strcmp(progname, "halt") ? "" : " [-p]", |
| 222 | + strcmp(progname, "reboot") ? "" : " [-k]"); |
| 223 | fprintf(stderr, "\t-n: don't sync before halting the system\n"); |
| 224 | fprintf(stderr, "\t-w: only write a wtmp reboot record and exit.\n"); |
| 225 | fprintf(stderr, "\t-d: don't write a wtmp record.\n"); |
| 226 | @@ -74,6 +77,8 @@ |
| 227 | fprintf(stderr, "\t-i: shut down all network interfaces.\n"); |
| 228 | if (!strcmp(progname, "halt")) |
| 229 | fprintf(stderr, "\t-p: power down the system (if possible, otherwise halt).\n"); |
| 230 | + if (!strcmp(progname, "reboot")) |
| 231 | + fprintf(stderr, "\t-k: reboot the system using kexec.\n"); |
| 232 | exit(1); |
| 233 | } |
| 234 | |
| 235 | @@ -172,12 +177,14 @@ |
| 236 | int do_ifdown = 0; |
| 237 | int do_hddown = 0; |
| 238 | int do_poweroff = 0; |
| 239 | + int do_kexec = 0; |
| 240 | int c; |
| 241 | char *tm = NULL; |
| 242 | |
| 243 | /* |
| 244 | * Find out who we are |
| 245 | */ |
| 246 | + if (argv[0][0] == '-') argv[0]++; |
| 247 | if ((progname = strrchr(argv[0], '/')) != NULL) |
| 248 | progname++; |
| 249 | else |
| 250 | @@ -189,7 +196,7 @@ |
| 251 | /* |
| 252 | * Get flags |
| 253 | */ |
| 254 | - while((c = getopt(argc, argv, ":ihdfnpwt:")) != EOF) { |
| 255 | + while((c = getopt(argc, argv, ":ihdfnpwkt:")) != EOF) { |
| 256 | switch(c) { |
| 257 | case 'n': |
| 258 | do_sync = 0; |
| 259 | @@ -213,6 +220,9 @@ |
| 260 | case 'p': |
| 261 | do_poweroff = 1; |
| 262 | break; |
| 263 | + case 'k': |
| 264 | + do_kexec = 1; |
| 265 | + break; |
| 266 | case 't': |
| 267 | tm = optarg; |
| 268 | break; |
| 269 | @@ -230,12 +240,37 @@ |
| 270 | (void)chdir("/"); |
| 271 | |
| 272 | if (!do_hard && !do_nothing) { |
| 273 | + c = get_runlevel(); |
| 274 | + |
| 275 | + /* |
| 276 | + * We can't reboot using kexec through this path. |
| 277 | + */ |
| 278 | + if (c != '6' && do_reboot && do_kexec) { |
| 279 | + fprintf(stderr, "ERROR: using -k at this" |
| 280 | + " runlevel requires also -f\n" |
| 281 | + " (You probably want instead to reboot" |
| 282 | + " normally and let your reboot\n" |
| 283 | + " script, usually /etc/init.d/reboot," |
| 284 | + " specify -k)\n"); |
| 285 | + exit(1); |
| 286 | + } |
| 287 | + |
| 288 | /* |
| 289 | * See if we are in runlevel 0 or 6. |
| 290 | */ |
| 291 | - c = get_runlevel(); |
| 292 | - if (c != '0' && c != '6') |
| 293 | - do_shutdown(do_reboot ? "-r" : "-h", tm); |
| 294 | + if (c != '0' && c != '6') { |
| 295 | + char *file; |
| 296 | + |
| 297 | + if (do_poweroff) { |
| 298 | + file = strdup("/poweroff"); |
| 299 | + } else { |
| 300 | + file = strdup("/halt"); |
| 301 | + } |
| 302 | + close(open(file, O_CREAT|O_RDWR, 0644)); |
| 303 | + free(file); |
| 304 | + |
| 305 | + do_shutdown(do_reboot ? "-r" : "-h", tm); |
| 306 | + } |
| 307 | } |
| 308 | |
| 309 | /* |
| 310 | @@ -263,6 +298,16 @@ |
| 311 | if (do_nothing) exit(0); |
| 312 | |
| 313 | if (do_reboot) { |
| 314 | + /* |
| 315 | + * kexec or reboot |
| 316 | + */ |
| 317 | + if (do_kexec) { |
| 318 | + init_reboot(BMAGIC_KEXEC); |
| 319 | + } |
| 320 | + |
| 321 | + /* |
| 322 | + * Fall through if failed |
| 323 | + */ |
| 324 | init_reboot(BMAGIC_REBOOT); |
| 325 | } else { |
| 326 | /* |
| 327 | diff -Naur sysvinit-2.86.orig/src/init.c sysvinit-2.86/src/init.c |
| 328 | --- sysvinit-2.86.orig/src/init.c 2004-07-30 05:16:20.000000000 -0700 |
| 329 | +++ sysvinit-2.86/src/init.c 2009-01-07 14:02:51.000000000 -0800 |
| 330 | @@ -185,6 +185,7 @@ |
| 331 | {"RU",RUNNING}, |
| 332 | {"DE",DEMAND}, |
| 333 | {"XD",XECUTED}, |
| 334 | + {"WT",WAITING}, |
| 335 | {NULL,0} |
| 336 | }; |
| 337 | |
| 338 | @@ -466,7 +467,7 @@ |
| 339 | |
| 340 | if (maxproclen > 2) { |
| 341 | memset(argv0, 0, maxproclen); |
| 342 | - strncpy(argv0, buf, maxproclen - 2); |
| 343 | + strncpy(argv0, buf, maxproclen - 1); |
| 344 | } |
| 345 | |
| 346 | return len; |
| 347 | @@ -527,8 +528,10 @@ |
| 348 | /* |
| 349 | * Retry the open five times. |
| 350 | */ |
| 351 | - for(f = 0; f < 5; f++) |
| 352 | + for(f = 0; f < 5; f++) { |
| 353 | if ((fd = open(console_dev, m)) >= 0) break; |
| 354 | + usleep(100); |
| 355 | + } |
| 356 | |
| 357 | if (fd < 0) return fd; |
| 358 | |
| 359 | @@ -949,11 +952,30 @@ |
| 360 | sigprocmask(SIG_SETMASK, &omask, NULL); |
| 361 | |
| 362 | /* |
| 363 | + * Update utmp/wtmp file prior to starting |
| 364 | + * any child. This MUST be done right here in |
| 365 | + * the child process in order to prevent a race |
| 366 | + * condition that occurs when the child |
| 367 | + * process' time slice executes before the |
| 368 | + * parent (can and does happen in a uniprocessor |
| 369 | + * environment). If the child is a getty and |
| 370 | + * the race condition happens, then init's utmp |
| 371 | + * update will happen AFTER the getty runs |
| 372 | + * and expects utmp to be updated already! |
| 373 | + * |
| 374 | + * Do NOT log if process field starts with '+' |
| 375 | + * FIXME: that's for compatibility with *very* |
| 376 | + * old getties - probably it can be taken out. |
| 377 | + */ |
| 378 | + if (ch->action == RESPAWN && ch->process[0] != '+') |
| 379 | + write_utmp_wtmp("", ch->id, getpid(), INIT_PROCESS, ""); |
| 380 | + |
| 381 | + /* |
| 382 | * In sysinit, boot, bootwait or single user mode: |
| 383 | * for any wait-type subprocess we _force_ the console |
| 384 | * to be its controlling tty. |
| 385 | */ |
| 386 | - if (strchr("*#sS", runlevel) && ch->flags & WAITING) { |
| 387 | + if ((strchr("*#sS", runlevel) || (ch->id[0] == 'l' && isdigit(ch->id[1]))) && ch->flags & WAITING) { |
| 388 | /* |
| 389 | * We fork once extra. This is so that we can |
| 390 | * wait and change the process group and session |
| 391 | @@ -1088,15 +1110,7 @@ |
| 392 | case ONDEMAND: |
| 393 | case RESPAWN: |
| 394 | ch->flags |= RUNNING; |
| 395 | - if (spawn(ch, &(ch->pid)) < 0) break; |
| 396 | - /* |
| 397 | - * Do NOT log if process field starts with '+' |
| 398 | - * FIXME: that's for compatibility with *very* |
| 399 | - * old getties - probably it can be taken out. |
| 400 | - */ |
| 401 | - if (ch->process[0] != '+') |
| 402 | - write_utmp_wtmp("", ch->id, ch->pid, |
| 403 | - INIT_PROCESS, ""); |
| 404 | + (void)spawn(ch, &(ch->pid)); |
| 405 | break; |
| 406 | } |
| 407 | } |
| 408 | @@ -1373,14 +1387,14 @@ |
| 409 | case 0: /* Send TERM signal */ |
| 410 | if (talk) |
| 411 | initlog(L_CO, |
| 412 | - "Sending processes the TERM signal"); |
| 413 | + "Sending processes started by init the TERM signal"); |
| 414 | kill(-(ch->pid), SIGTERM); |
| 415 | foundOne = 1; |
| 416 | break; |
| 417 | case 1: /* Send KILL signal and collect status */ |
| 418 | if (talk) |
| 419 | initlog(L_CO, |
| 420 | - "Sending processes the KILL signal"); |
| 421 | + "Sending processes started by init the KILL signal"); |
| 422 | kill(-(ch->pid), SIGKILL); |
| 423 | break; |
| 424 | } |
| 425 | @@ -1884,7 +1898,7 @@ |
| 426 | * The existing init process execs a new init binary. |
| 427 | */ |
| 428 | env = init_buildenv(0); |
| 429 | - execl(myname, myname, "--init", NULL, env); |
| 430 | + execle(myname, myname, "--init", NULL, env); |
| 431 | |
| 432 | /* |
| 433 | * We shouldn't be here, something failed. |
| 434 | diff -Naur sysvinit-2.86.orig/src/killall5.c sysvinit-2.86/src/killall5.c |
| 435 | --- sysvinit-2.86.orig/src/killall5.c 2004-07-30 05:16:23.000000000 -0700 |
| 436 | +++ sysvinit-2.86/src/killall5.c 2009-01-07 14:10:41.000000000 -0800 |
| 437 | @@ -51,9 +51,8 @@ |
| 438 | char *argv0base; /* `basename argv[1]` */ |
| 439 | char *argv1; /* Name as found out from argv[1] */ |
| 440 | char *argv1base; /* `basename argv[1]` */ |
| 441 | + char *pathname; /* full path to executable */ |
| 442 | char *statname; /* the statname without braces */ |
| 443 | - ino_t ino; /* Inode number */ |
| 444 | - dev_t dev; /* Device it is on */ |
| 445 | pid_t pid; /* Process ID. */ |
| 446 | int sid; /* Session ID. */ |
| 447 | int kernel; /* Kernel thread or zombie. */ |
| 448 | @@ -172,7 +171,6 @@ |
| 449 | FILE *fp; |
| 450 | PROC *p, *n; |
| 451 | struct dirent *d; |
| 452 | - struct stat st; |
| 453 | char path[256]; |
| 454 | char buf[256]; |
| 455 | char *s, *q; |
| 456 | @@ -191,6 +189,8 @@ |
| 457 | n = p->next; |
| 458 | if (p->argv0) free(p->argv0); |
| 459 | if (p->argv1) free(p->argv1); |
| 460 | + if (p->pathname) free(p->pathname); |
| 461 | + if (p->statname) free(p->statname); |
| 462 | free(p); |
| 463 | } |
| 464 | plist = NULL; |
| 465 | @@ -248,6 +248,7 @@ |
| 466 | p->sid = 0; |
| 467 | nsyslog(LOG_ERR, "can't read sid from %s\n", |
| 468 | path); |
| 469 | + if (p->statname) free(p->statname); |
| 470 | free(p); |
| 471 | continue; |
| 472 | } |
| 473 | @@ -300,15 +301,18 @@ |
| 474 | |
| 475 | } else { |
| 476 | /* Process disappeared.. */ |
| 477 | + if (p->statname) free(p->statname); |
| 478 | free(p); |
| 479 | continue; |
| 480 | } |
| 481 | |
| 482 | /* Try to stat the executable. */ |
| 483 | snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name); |
| 484 | - if (stat(path, &st) == 0) { |
| 485 | - p->dev = st.st_dev; |
| 486 | - p->ino = st.st_ino; |
| 487 | + p->pathname = (char *)xmalloc(PATH_MAX); |
| 488 | + if (readlink(path, p->pathname, PATH_MAX) == -1) { |
| 489 | + p->pathname = NULL; |
| 490 | + } else { |
| 491 | + p->pathname[PATH_MAX-1] = '\0'; |
| 492 | } |
| 493 | |
| 494 | /* Link it into the list. */ |
| 495 | @@ -372,14 +376,14 @@ |
| 496 | { |
| 497 | PROC *p; |
| 498 | PIDQ_HEAD *q; |
| 499 | - struct stat st; |
| 500 | char *s; |
| 501 | int dostat = 0; |
| 502 | int foundone = 0; |
| 503 | int ok = 0; |
| 504 | + char *real_path; |
| 505 | |
| 506 | /* Try to stat the executable. */ |
| 507 | - if (prog[0] == '/' && stat(prog, &st) == 0) dostat++; |
| 508 | + if (prog[0] == '/' && (real_path = canonicalize_file_name(prog))) dostat++; |
| 509 | |
| 510 | /* Get basename of program. */ |
| 511 | if ((s = strrchr(prog, '/')) == NULL) |
| 512 | @@ -390,10 +394,10 @@ |
| 513 | q = (PIDQ_HEAD *)xmalloc(sizeof(PIDQ_HEAD)); |
| 514 | q = init_pid_q(q); |
| 515 | |
| 516 | - /* First try to find a match based on dev/ino pair. */ |
| 517 | + /* First try to find a match based on pathname. */ |
| 518 | if (dostat) { |
| 519 | for (p = plist; p; p = p->next) { |
| 520 | - if (p->dev == st.st_dev && p->ino == st.st_ino) { |
| 521 | + if (p->pathname && strcmp(real_path, p->pathname) == 0) { |
| 522 | add_pid_to_q(q, p); |
| 523 | foundone++; |
| 524 | } |
| 525 | @@ -408,11 +412,14 @@ |
| 526 | ok += (p->argv0 && strcmp(p->argv0, prog) == 0); |
| 527 | ok += (p->argv0 && strcmp(p->argv0base, s) == 0); |
| 528 | |
| 529 | + if (prog[0] == '/' && p->pathname && strcmp(prog, p->pathname)) |
| 530 | + ok = 0; |
| 531 | + |
| 532 | /* For scripts, compare argv[1] as well. */ |
| 533 | if (scripts_too && p->argv1 && |
| 534 | !strncmp(p->statname, p->argv1base, STATNAMELEN)) { |
| 535 | ok += (strcmp(p->argv1, prog) == 0); |
| 536 | - ok += (strcmp(p->argv1base, s) == 0); |
| 537 | + if (prog[0] != '/') ok += (strcmp(p->argv1base, s) == 0); |
| 538 | } |
| 539 | |
| 540 | /* |
| 541 | @@ -476,16 +483,22 @@ |
| 542 | int f; |
| 543 | int first = 1; |
| 544 | int i, oind, opt, flags = 0; |
| 545 | + int chroot_check = 0; |
| 546 | + struct stat st; |
| 547 | + char tmp[512]; |
| 548 | |
| 549 | for (oind = PIDOF_OMITSZ-1; oind > 0; oind--) |
| 550 | opid[oind] = 0; |
| 551 | opterr = 0; |
| 552 | |
| 553 | - while ((opt = getopt(argc,argv,"ho:sx")) != EOF) switch (opt) { |
| 554 | + while ((opt = getopt(argc,argv,"hco:sx")) != EOF) switch (opt) { |
| 555 | case '?': |
| 556 | nsyslog(LOG_ERR,"invalid options on command line!\n"); |
| 557 | closelog(); |
| 558 | exit(1); |
| 559 | + case 'c': |
| 560 | + if (geteuid() == 0) chroot_check = 1; |
| 561 | + break; |
| 562 | case 'o': |
| 563 | if (oind >= PIDOF_OMITSZ -1) { |
| 564 | nsyslog(LOG_ERR,"omit pid buffer size %d " |
| 565 | @@ -518,6 +531,16 @@ |
| 566 | argc -= optind; |
| 567 | argv += optind; |
| 568 | |
| 569 | + /* Check if we are in a chroot */ |
| 570 | + if (chroot_check) { |
| 571 | + snprintf(tmp, 512, "/proc/%d/root", getpid()); |
| 572 | + if (stat(tmp, &st) < 0) { |
| 573 | + nsyslog(LOG_ERR, "stat failed for %s!\n", tmp); |
| 574 | + closelog(); |
| 575 | + exit(1); |
| 576 | + } |
| 577 | + } |
| 578 | + |
| 579 | /* Print out process-ID's one by one. */ |
| 580 | readproc(); |
| 581 | for(f = 0; f < argc; f++) { |
| 582 | @@ -541,6 +564,16 @@ |
| 583 | else |
| 584 | spid = 1; |
| 585 | } |
| 586 | + if (chroot_check) { |
| 587 | + struct stat st2; |
| 588 | + snprintf(tmp, 512, "/proc/%d/root", |
| 589 | + p->pid); |
| 590 | + if (stat(tmp, &st2) < 0 || |
| 591 | + st.st_dev != st2.st_dev || |
| 592 | + st.st_ino != st2.st_ino) { |
| 593 | + continue; |
| 594 | + } |
| 595 | + } |
| 596 | if (!first) |
| 597 | printf(" "); |
| 598 | printf("%d", p->pid); |
| 599 | diff -Naur sysvinit-2.86.orig/src/last.c sysvinit-2.86/src/last.c |
| 600 | --- sysvinit-2.86.orig/src/last.c 2004-07-30 05:16:26.000000000 -0700 |
| 601 | +++ sysvinit-2.86/src/last.c 2009-01-07 11:18:38.000000000 -0800 |
| 602 | @@ -307,14 +307,15 @@ |
| 603 | struct sockaddr *sa; |
| 604 | int salen, flags; |
| 605 | unsigned int topnibble; |
| 606 | + unsigned int azero = 0, sitelocal = 0; |
| 607 | int mapped = 0; |
| 608 | |
| 609 | flags = useip ? NI_NUMERICHOST : 0; |
| 610 | |
| 611 | /* |
| 612 | * IPv4 or IPv6 ? We use 2 heuristics: |
| 613 | - * 1. Current IPv6 range uses 2000-3fff. Outside of |
| 614 | - * that is illegal and must be IPv4. |
| 615 | + * 1. Current IPv6 range uses 2000-3fff or fec0-feff. |
| 616 | + * Outside of that is illegal and must be IPv4. |
| 617 | * 2. If last 3 bytes are 0, must be IPv4 |
| 618 | * 3. If IPv6 in IPv4, handle as IPv4 |
| 619 | * |
| 620 | @@ -323,7 +324,11 @@ |
| 621 | if (a[0] == 0 && a[1] == 0 && a[2] == htonl (0xffff)) |
| 622 | mapped = 1; |
| 623 | topnibble = ntohl((unsigned int)a[0]) >> 28; |
| 624 | - if (topnibble < 2 || topnibble > 3 || mapped || |
| 625 | + |
| 626 | + azero = ntohl((unsigned int)a[0]) >> 16; |
| 627 | + sitelocal = (azero >= 0xfec0 && azero <= 0xfeff) ? 1 : 0; |
| 628 | + |
| 629 | + if (((topnibble < 2 || topnibble > 3) && (!sitelocal)) || mapped || |
| 630 | (a[1] == 0 && a[2] == 0 && a[3] == 0)) { |
| 631 | /* IPv4 */ |
| 632 | sin.sin_family = AF_INET; |
| 633 | diff -Naur sysvinit-2.86.orig/src/reboot.h sysvinit-2.86/src/reboot.h |
| 634 | --- sysvinit-2.86.orig/src/reboot.h 2004-06-09 05:47:45.000000000 -0700 |
| 635 | +++ sysvinit-2.86/src/reboot.h 2009-01-07 11:07:06.000000000 -0800 |
| 636 | @@ -32,5 +32,8 @@ |
| 637 | # define BMAGIC_POWEROFF BMAGIC_HALT |
| 638 | #endif |
| 639 | |
| 640 | +/* for kexec support */ |
| 641 | +#define BMAGIC_KEXEC 0x45584543 |
| 642 | + |
| 643 | #define init_reboot(magic) reboot(magic) |
| 644 | |
| 645 | diff -Naur sysvinit-2.86.orig/src/shutdown.c sysvinit-2.86/src/shutdown.c |
| 646 | --- sysvinit-2.86.orig/src/shutdown.c 2004-07-30 04:59:04.000000000 -0700 |
| 647 | +++ sysvinit-2.86/src/shutdown.c 2009-01-07 11:09:43.000000000 -0800 |
| 648 | @@ -102,7 +102,7 @@ |
| 649 | void usage(void) |
| 650 | { |
| 651 | fprintf(stderr, |
| 652 | - "Usage:\t shutdown [-akrhHPfnc] [-t secs] time [warning message]\n" |
| 653 | + "Usage:\t shutdown [-akrhPHfFnc] [-t sec] time [warning message]\n" |
| 654 | "\t\t -a: use /etc/shutdown.allow\n" |
| 655 | "\t\t -k: don't really shutdown, only warn.\n" |
| 656 | "\t\t -r: reboot after shutdown.\n" |
| 657 | @@ -460,6 +460,7 @@ |
| 658 | |
| 659 | if (getuid() != 0) { |
| 660 | fprintf(stderr, "shutdown: you must be root to do that!\n"); |
| 661 | + usage(); |
| 662 | exit(1); |
| 663 | } |
| 664 | strcpy(down_level, "1"); |
| 665 | diff -Naur sysvinit-2.86.orig/src/utmp.c sysvinit-2.86/src/utmp.c |
| 666 | --- sysvinit-2.86.orig/src/utmp.c 1999-06-09 04:11:33.000000000 -0700 |
| 667 | +++ sysvinit-2.86/src/utmp.c 2009-01-07 11:11:29.000000000 -0800 |
| 668 | @@ -47,6 +47,7 @@ |
| 669 | int fd; |
| 670 | struct utmp utmp; |
| 671 | struct utsname uname_buf; |
| 672 | + struct timeval tv; |
| 673 | |
| 674 | /* |
| 675 | * Try to open the wtmp file. Note that we even try |
| 676 | @@ -76,7 +77,9 @@ |
| 677 | */ |
| 678 | memset(&utmp, 0, sizeof(utmp)); |
| 679 | #if defined(__GLIBC__) |
| 680 | - gettimeofday(&utmp.ut_tv, NULL); |
| 681 | + gettimeofday(&tv, NULL); |
| 682 | + utmp.ut_tv.tv_sec = tv.tv_sec; |
| 683 | + utmp.ut_tv.tv_usec = tv.tv_usec; |
| 684 | #else |
| 685 | time(&utmp.ut_time); |
| 686 | #endif |
| 687 | @@ -113,6 +116,7 @@ |
| 688 | struct utmp utmp; |
| 689 | struct utmp tmp; |
| 690 | struct utmp *utmptr; |
| 691 | + struct timeval tv; |
| 692 | |
| 693 | /* |
| 694 | * Can't do much if UTMP_FILE is not present. |
| 695 | @@ -144,7 +148,9 @@ |
| 696 | utmp.ut_pid = pid; |
| 697 | strncpy(utmp.ut_id, id, sizeof(utmp.ut_id)); |
| 698 | #if defined(__GLIBC__) |
| 699 | - gettimeofday(&utmp.ut_tv, NULL); |
| 700 | + gettimeofday(&tv, NULL); |
| 701 | + utmp.ut_tv.tv_sec = tv.tv_sec; |
| 702 | + utmp.ut_tv.tv_usec = tv.tv_usec; |
| 703 | #else |
| 704 | time(&utmp.ut_time); |
| 705 | #endif |