File: nosysrq.c

package info (click to toggle)
vlock 2.2.2-13
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 580 kB
  • sloc: ansic: 2,946; sh: 871; makefile: 208
file content (110 lines) | stat: -rw-r--r-- 2,744 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/* nosysrq.c -- SysRq protection plugin for vlock,
 *              the VT locking program for linux
 *
 * This program is copyright (C) 2007 Frank Benkstein, and is free
 * software which is freely distributable under the terms of the
 * GNU General Public License version 2, included as the file COPYING in this
 * distribution.  It is NOT public domain software, and any
 * redistribution not permitted by the GNU General Public License is
 * expressly forbidden without prior written permission from
 * the author.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include "vlock_plugin.h"

const char *preceeds[] = { "new", "all", NULL };
const char *depends[] = { "all", NULL };

#define SYSRQ_PATH "/proc/sys/kernel/sysrq"
#define SYSRQ_DISABLE_VALUE "0\n"

struct sysrq_context {
  FILE *file;
  char value[32];
};

/* Disable SysRq and save old value in context. */
bool vlock_start(void **ctx_ptr)
{
  struct sysrq_context *ctx;

  /* Allocate the context. */
  if ((ctx = malloc(sizeof *ctx)) == NULL)
    return false;

  /* XXX: add optional PAM check here */

  /* Open the SysRq sysctl file for reading and writing. */
  if ((ctx->file = fopen(SYSRQ_PATH, "r+")) == NULL) {
    perror("vlock-nosysrq: could not open '" SYSRQ_PATH "'");
    if (errno == ENOENT)
      goto nothing_to_do;
    else
      goto err;
  }

  /* Read the old value. */
  if (fgets(ctx->value, sizeof ctx->value, ctx->file) == NULL) {
    perror("vlock-nosysrq: could not read from '" SYSRQ_PATH "'");
    goto err;
  }

  /* Check whether all data was read. */
  if (feof(ctx->file) != 0) {
    fprintf(stderr, "vlock-nosysrq: sysrq buffer to small: %zu\n",
            sizeof ctx->value);
    goto err;
  }

  /* Check if SysRq was already disabled. */
  if (strcmp(SYSRQ_DISABLE_VALUE, ctx->value) == 0)
    goto nothing_to_do;

  /* Disable SysRq. */
  if (fseek(ctx->file, 0, SEEK_SET) < 0
      || ftruncate(fileno(ctx->file), 0) < 0
      || fputs(SYSRQ_DISABLE_VALUE, ctx->file) < 0
      || fflush(ctx->file) < 0) {
    perror("vlock-nosysrq: could not write disable value to '" SYSRQ_PATH "'");
    goto err;
  }

  *ctx_ptr = ctx;
  return true;

nothing_to_do:
  free(ctx);
  *ctx_ptr = NULL;
  return true;

err:
  errno = 0;
  free(ctx);
  return false;
}


/* Restore old SysRq value. */
bool vlock_end(void **ctx_ptr)
{
  struct sysrq_context *ctx = *ctx_ptr;

  if (ctx == NULL)
    return true;

  /* Restore SysRq. */
  if (fseek(ctx->file, 0, SEEK_SET) < 0
      || ftruncate(fileno(ctx->file), 0) < 0
      || fputs(ctx->value, ctx->file) < 0 || fflush(ctx->file) < 0)
    perror("vlock-nosysrq: could not write old value to '" SYSRQ_PATH "'");

  free(ctx);
  return true;
}