[ale] Rebooting remotely without a usable /

Michael B. Trausch mbt at zest.trausch.us
Mon Sep 21 07:19:50 EDT 2009


On Mon, 2009-09-21 at 06:29 -0400, Matt Rideout wrote:
> I have a server that's having issues with its / which prevent shutdown, 
> reboot, init, etc from being accessible. This could be a hardware or 
> firmware issue, so I'd like to reboot, and diagnose it remotely so that 
> I'll know whether to order any hardware before going on-site.
> 
> I can SSH in, and have an IP KVM hooked up, but have no remote power 
> management. The SysRq trick isn't working through the KVM. It seems like 
> there should be a way to reboot through /proc, but I'm drawing a blank. 
> Any ideas?

What CPU is the server, and at what bit-width does it run?

Do you have access to gcc and/or as on that server?  If so, you can use
the reboot(2) syscall to force the system to reboot.  This should do it,
if you have access to gcc, you can use the pasted code below.  If you do
not have access to gcc (or cannot write an assembly system call and use
as to assemble it), the answer to the questions above would (likely)
permit me (or anyone else on this list) to create an ELF binary using
the code below for whatever system you're running.

If you do not have GLIBC, but instead an older Linux libc, use the
command:

gcc -DNO_GLIBC -o force-reboot force-reboot.c

If you have glibc, it is simply:

gcc -o force-reboot force-reboot.c

Here's the code:

/*
 * force-reboot.c - In an emergency, force Linux to reboot.
 *
 * See man 2 reboot.
 */
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#ifdef NO_GLIBC
#include <linux/reboot.h>
#else
#include <sys/reboot.h>
#endif

#ifdef NO_GLIBC
#ifndef LINUX_REBOOT_MAGIC1
#define LINUX_REBOOT_MAGIC1 0xfee1dead
#endif

#ifndef LINUX_REBOOT_MAGIC2
#define LINUX_REBOOT_MAGIC2 0x28121969
#endif

#ifndef LINUX_REBOOT_MAGIC2A
#define LINUX_REBOOT_MAGIC2A 0x05121996
#endif

#ifndef LINUX_REBOOT_MAGIC2B
#define LINUX_REBOOT_MAGIC2B 0x16041998
#endif

#ifndef LINUX_REBOOT_MAGIC2C
#define LINUX_REBOOT_MAGIC2C 0x20112000
#endif
#endif /* NO_GLIBC */

#ifndef LINUX_REBOOT_CMD_RESTART
#define LINUX_REBOOT_CMD_RESTART 0x1234567
#endif

#ifndef LINUX_REBOOT_CMD_HALT
#define LINUX_REBOOT_CMD_HALT 0xcdef0123
#endif

#ifndef LINUX_REBOOT_CMD_POWER_OFF
#define LINUX_REBOOT_CMD_POWER_OFF 0x4321fedc
#endif

#ifndef LINUX_REBOOT_CMD_RESTART2
#define LINUX_REBOOT_CMD_RESTART2 0xa1b3c3d4
#endif

#ifndef LINUX_REBOOT_CMD_CAD_ON
#define LINUX_REBOOT_CMD_CAD_ON 0x89abcdef
#endif

#ifndef LINUX_REBOOT_CMD_CAD_OFF
#define LINUX_REBOOT_CMD_CAD_OFF 0x00000000
#endif

static void do_reboot(int command);

int
main(int argc, char *argv[]) {
  int reboot_command;

  if(argc == 1) {
    fprintf(stderr, "No command given.\n");
    fprintf(stderr, "Commands: RESTART, HALT, POWER_OFF, CAD_ON,
CAD_OFF.\n");
    return(2);
  } else if(strcasecmp(argv[1], "RESTART") == 0) {
    reboot_command = LINUX_REBOOT_CMD_RESTART;
  } else if(strcasecmp(argv[1], "HALT") == 0) {
    reboot_command = LINUX_REBOOT_CMD_HALT;
  } else if(strcasecmp(argv[1], "POWER_OFF") == 0) {
    reboot_command = LINUX_REBOOT_CMD_POWER_OFF;
  } else if(strcasecmp(argv[1], "RESTART2") == 0) {
    fprintf(stderr, "RESTART2 not supported. Try RESTART.\n");
    return(1);
  } else if(strcasecmp(argv[1], "CAD_ON") == 0) {
    reboot_command = LINUX_REBOOT_CMD_CAD_ON;
  } else if(strcasecmp(argv[1], "CAD_OFF") == 0) {
    reboot_command = LINUX_REBOOT_CMD_CAD_OFF;
  } else {
    fprintf(stderr, "%s not supported.\n", argv[1]);
    fprintf(stderr, "Commands: RESTART, HALT, POWER_OFF, CAD_ON,
CAD_OFF.\n");
    return(2);
  }

  do_reboot(reboot_command);

  // Not reached, unless command was CAD_ON or CAD_OFF.
  return(0);
}

static void
do_reboot(int cmd) {
  int reboot_status = 0;

  // Flush filesystem buffers before rebooting.
  sync();

  #ifdef NO_GLIBC
  // Old libc.
  reboot_status = reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd,
NULL);
  #else
  // glibc uses a wrapper around the system call.
  reboot_status = reboot(cmd);
  #endif

  if(reboot_status == -1) {
    if(errno == EPERM) {
      fprintf(stderr, "Permission denied.  Are you root?\n");
    }
  }
}


-- 
Blog:  http://mike.trausch.us/blog/
Misc. Software:  http://mike.trausch.us/software/

“The greater danger for most of us lies not in setting our aim too
high and falling short; but in setting our aim too low, and achieving
our mark.” —Michelangelo



More information about the Ale mailing list