Coverage Report

Created: 2024-05-21 06:33

/src/util-linux/libblkid/src/superblocks/swap.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 1999 by Andries Brouwer
3
 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
4
 * Copyright (C) 2001 by Andreas Dilger
5
 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
6
 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
7
 *
8
 * This file may be redistributed under the terms of the
9
 * GNU Lesser General Public License.
10
 */
11
#include <stdio.h>
12
#include <stdlib.h>
13
#include <unistd.h>
14
#include <string.h>
15
#include <errno.h>
16
#include <ctype.h>
17
#include <stdint.h>
18
19
#include "superblocks.h"
20
21
/* linux-2.6/include/linux/swap.h */
22
struct swap_header_v1_2 {
23
     /* char    bootbits[1024]; */ /* Space for disklabel etc. */
24
  uint32_t  version;
25
  uint32_t  lastpage;
26
  uint32_t  nr_badpages;
27
  unsigned char uuid[16];
28
  unsigned char volume[16];
29
  uint32_t  padding[117];
30
  uint32_t  badpages[1];
31
} __attribute__((packed));
32
33
#define PAGESIZE_MIN  0xff6 /* 4086 (arm, i386, ...) */
34
#define PAGESIZE_MAX  0xfff6  /* 65526 (ia64) */
35
36
1.10k
#define TOI_MAGIC_STRING  "\xed\xc3\x02\xe9\x98\x56\xe5\x0c"
37
686
#define TOI_MAGIC_STRLEN  (sizeof(TOI_MAGIC_STRING) - 1)
38
39
static void swap_set_info_swap1(blkid_probe pr,
40
    const struct blkid_idmag *mag,
41
    const struct swap_header_v1_2 *hdr)
42
7
{
43
7
  enum blkid_endianness endianness = le32_to_cpu(hdr->version) == 1 ?
44
4
    BLKID_ENDIANNESS_LITTLE : BLKID_ENDIANNESS_BIG;
45
7
  blkid_probe_set_fsendianness(pr, endianness);
46
47
7
  uint32_t pagesize = mag->sboff + mag->len;
48
7
  blkid_probe_set_fsblocksize(pr, pagesize);
49
50
7
  uint32_t lastpage = endianness == BLKID_ENDIANNESS_LITTLE ?
51
4
    le32_to_cpu(hdr->lastpage) : be32_to_cpu(hdr->lastpage);
52
7
  blkid_probe_set_fssize(pr, (uint64_t) pagesize * lastpage);
53
7
}
54
55
static int swap_set_info(blkid_probe pr, const struct blkid_idmag *mag,
56
    const char *version)
57
596
{
58
596
  struct swap_header_v1_2 *hdr;
59
60
  /* Swap header always located at offset of 1024 bytes */
61
596
  hdr = (struct swap_header_v1_2 *) blkid_probe_get_buffer(pr, 1024,
62
596
        sizeof(struct swap_header_v1_2));
63
596
  if (!hdr)
64
0
    return errno ? -errno : 1;
65
66
  /* SWAPSPACE2 - check for wrong version or zeroed pagecount */
67
596
  if (strcmp(version, "1") == 0) {
68
263
    if (hdr->version != 1 && swab32(hdr->version) != 1) {
69
248
      DBG(LOWPROBE, ul_debug("incorrect swap version"));
70
248
      return 1;
71
248
    }
72
15
    if (hdr->lastpage == 0) {
73
8
      DBG(LOWPROBE, ul_debug("not set last swap page"));
74
8
      return 1;
75
8
    }
76
7
    swap_set_info_swap1(pr, mag, hdr);
77
7
  }
78
79
  /* arbitrary sanity check.. is there any garbage down there? */
80
340
  if (hdr->padding[32] == 0 && hdr->padding[33] == 0) {
81
105
    if (hdr->volume[0] && blkid_probe_set_label(pr, hdr->volume,
82
50
        sizeof(hdr->volume)) < 0)
83
0
      return 1;
84
105
    if (blkid_probe_set_uuid(pr, hdr->uuid) < 0)
85
0
      return 1;
86
105
  }
87
88
340
  blkid_probe_set_version(pr, version);
89
340
  return 0;
90
340
}
91
92
static int probe_swap(blkid_probe pr, const struct blkid_idmag *mag)
93
269
{
94
269
  const unsigned char *buf;
95
96
269
  if (!mag)
97
0
    return 1;
98
99
  /* TuxOnIce keeps valid swap header at the end of the 1st page */
100
269
  buf = blkid_probe_get_buffer(pr, 0, TOI_MAGIC_STRLEN);
101
269
  if (!buf)
102
0
    return errno ? -errno : 1;
103
104
269
  if (memcmp(buf, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN) == 0)
105
4
    return 1;  /* Ignore swap signature, it's TuxOnIce */
106
107
265
  if (!memcmp(mag->magic, "SWAP-SPACE", mag->len)) {
108
    /* swap v0 doesn't support LABEL or UUID */
109
2
    blkid_probe_set_version(pr, "0");
110
2
    return 0;
111
112
2
  }
113
114
263
  if (!memcmp(mag->magic, "SWAPSPACE2", mag->len))
115
263
    return swap_set_info(pr, mag, "1");
116
117
0
  return 1;
118
263
}
119
120
static int probe_swsuspend(blkid_probe pr, const struct blkid_idmag *mag)
121
333
{
122
333
  if (!mag)
123
0
    return 1;
124
333
  if (!memcmp(mag->magic, "S1SUSPEND", mag->len))
125
23
    return swap_set_info(pr, mag, "s1suspend");
126
310
  if (!memcmp(mag->magic, "S2SUSPEND", mag->len))
127
48
    return swap_set_info(pr, mag, "s2suspend");
128
262
  if (!memcmp(mag->magic, "ULSUSPEND", mag->len))
129
114
    return swap_set_info(pr, mag, "ulsuspend");
130
148
  if (!memcmp(mag->magic, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN))
131
49
    return swap_set_info(pr, mag, "tuxonice");
132
99
  if (!memcmp(mag->magic, "LINHIB0001", mag->len))
133
99
    return swap_set_info(pr, mag, "linhib0001");
134
135
0
  return 1; /* no signature detected */
136
99
}
137
138
const struct blkid_idinfo swap_idinfo =
139
{
140
  .name   = "swap",
141
  .usage    = BLKID_USAGE_OTHER,
142
  .probefunc  = probe_swap,
143
  .minsz    = 10 * 4096,  /* 10 pages */
144
  .magics   =
145
  {
146
    { .magic = "SWAP-SPACE", .len = 10, .sboff = 0xff6 },
147
    { .magic = "SWAPSPACE2", .len = 10, .sboff = 0xff6 },
148
    { .magic = "SWAP-SPACE", .len = 10, .sboff = 0x1ff6 },
149
    { .magic = "SWAPSPACE2", .len = 10, .sboff = 0x1ff6 },
150
    { .magic = "SWAP-SPACE", .len = 10, .sboff = 0x3ff6 },
151
    { .magic = "SWAPSPACE2", .len = 10, .sboff = 0x3ff6 },
152
    { .magic = "SWAP-SPACE", .len = 10, .sboff = 0x7ff6 },
153
    { .magic = "SWAPSPACE2", .len = 10, .sboff = 0x7ff6 },
154
    { .magic = "SWAP-SPACE", .len = 10, .sboff = 0xfff6 },
155
    { .magic = "SWAPSPACE2", .len = 10, .sboff = 0xfff6 },
156
    { NULL }
157
  }
158
};
159
160
161
const struct blkid_idinfo swsuspend_idinfo =
162
{
163
  .name   = "swsuspend",
164
  .usage    = BLKID_USAGE_OTHER,
165
  .probefunc  = probe_swsuspend,
166
  .minsz    = 10 * 4096,  /* 10 pages */
167
  .magics   =
168
  {
169
    { .magic = TOI_MAGIC_STRING, .len = TOI_MAGIC_STRLEN },
170
    { .magic = "S1SUSPEND", .len = 9, .sboff = 0xff6 },
171
    { .magic = "S2SUSPEND", .len = 9, .sboff = 0xff6 },
172
    { .magic = "ULSUSPEND", .len = 9, .sboff = 0xff6 },
173
    { .magic = "LINHIB0001", .len = 10, .sboff = 0xff6 },
174
175
    { .magic = "S1SUSPEND", .len = 9, .sboff = 0x1ff6 },
176
    { .magic = "S2SUSPEND", .len = 9, .sboff = 0x1ff6 },
177
    { .magic = "ULSUSPEND", .len = 9, .sboff = 0x1ff6 },
178
    { .magic = "LINHIB0001", .len = 10, .sboff = 0x1ff6 },
179
180
    { .magic = "S1SUSPEND", .len = 9, .sboff = 0x3ff6 },
181
    { .magic = "S2SUSPEND", .len = 9, .sboff = 0x3ff6 },
182
    { .magic = "ULSUSPEND", .len = 9, .sboff = 0x3ff6 },
183
    { .magic = "LINHIB0001", .len = 10, .sboff = 0x3ff6 },
184
185
    { .magic = "S1SUSPEND", .len = 9, .sboff = 0x7ff6 },
186
    { .magic = "S2SUSPEND", .len = 9, .sboff = 0x7ff6 },
187
    { .magic = "ULSUSPEND", .len = 9, .sboff = 0x7ff6 },
188
    { .magic = "LINHIB0001", .len = 10, .sboff = 0x7ff6 },
189
190
    { .magic = "S1SUSPEND", .len = 9, .sboff = 0xfff6 },
191
    { .magic = "S2SUSPEND", .len = 9, .sboff = 0xfff6 },
192
    { .magic = "ULSUSPEND", .len = 9, .sboff = 0xfff6 },
193
    { .magic = "LINHIB0001", .len = 10, .sboff = 0xfff6 },
194
    { NULL }
195
  }
196
};