Skip to content

Commit 3cbcbf9

Browse files
authored
add bladerf fpga images to snap (#799)
fix #798
1 parent 88fa644 commit 3cbcbf9

File tree

3 files changed

+331
-28
lines changed

3 files changed

+331
-28
lines changed

data/build_snap.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ cd ..
99
sed -i "s/version\: git/version\: $(python3 src/urh/version.py)/" snapcraft.yaml
1010

1111

12-
SNAPCRAFT_BUILD_ENVIRONMENT_CPU=4 SNAPCRAFT_BUILD_ENVIRONMENT_MEMORY=6G snapcraft
12+
SNAPCRAFT_BUILD_ENVIRONMENT_CPU=6 SNAPCRAFT_BUILD_ENVIRONMENT_MEMORY=18G snapcraft
1313
sudo snap install --dangerous urh*.snap
1414
urh

data/semwraplib.c

+280
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
// Source: https://github.com/snapcore/snapcraft-preloads/blob/master/semaphores/preload-semaphores.c
2+
3+
#ifndef _GNU_SOURCE
4+
#define _GNU_SOURCE
5+
#endif
6+
7+
/*
8+
* $ gcc -Wall -fPIC -shared -o mylib.so ./lib.c -ldl
9+
* $ LD_PRELOAD=./mylib.so ...
10+
*/
11+
12+
#include <dlfcn.h>
13+
14+
#include <sys/types.h>
15+
#include <stdio.h>
16+
#include <semaphore.h>
17+
#include <string.h>
18+
#include <stdlib.h>
19+
#include <errno.h>
20+
#include <sys/stat.h>
21+
#include <unistd.h>
22+
#include <fcntl.h>
23+
#include <stdarg.h>
24+
#include <limits.h>
25+
26+
static sem_t *(*original_sem_open) (const char *, int, ...);
27+
static int (*original_sem_unlink) (const char *);
28+
29+
// Format is: 'sem.snap.SNAP_NAME.<something>'. So: 'sem.snap.' + '.' = 10
30+
#define MAX_NAME_SIZE NAME_MAX - 10
31+
#define SHM_DIR "/dev/shm"
32+
33+
void debug(char *s, ...)
34+
{
35+
if (secure_getenv("SEMWRAP_DEBUG")) {
36+
va_list va;
37+
va_start(va, s);
38+
fprintf(stderr, "SEMWRAP: ");
39+
vfprintf(stderr, s, va);
40+
va_end(va);
41+
fprintf(stderr, "\n");
42+
}
43+
}
44+
45+
const char *get_snap_name(void)
46+
{
47+
const char *snapname = getenv("SNAP_INSTANCE_NAME");
48+
if (!snapname) {
49+
snapname = getenv("SNAP_NAME");
50+
}
51+
if (!snapname) {
52+
debug("SNAP_NAME and SNAP_INSTANCE_NAME not set");
53+
}
54+
return snapname;
55+
}
56+
57+
int rewrite(const char *snapname, const char *name, char *rewritten,
58+
size_t rmax)
59+
{
60+
if (strlen(snapname) + strlen(name) > MAX_NAME_SIZE) {
61+
errno = ENAMETOOLONG;
62+
return -1;
63+
}
64+
65+
const char *tmp = name;
66+
if (tmp[0] == '/') {
67+
// If specified with leading '/', just strip it to avoid
68+
// having to mkdir(), etc
69+
tmp = &name[1];
70+
}
71+
72+
int n = snprintf(rewritten, rmax, "snap.%s.%s", snapname, tmp);
73+
if (n < 0 || n >= rmax) {
74+
fprintf(stderr, "snprintf truncated\n");
75+
return -1;
76+
}
77+
rewritten[rmax-1] = '\0';
78+
79+
return 0;
80+
}
81+
82+
sem_t *sem_open(const char *name, int oflag, ...)
83+
{
84+
mode_t mode;
85+
unsigned int value;
86+
87+
debug("sem_open()");
88+
debug("requested name: %s", name);
89+
90+
// lookup the libc's sem_open() if we haven't already
91+
if (!original_sem_open) {
92+
dlerror();
93+
original_sem_open = dlsym(RTLD_NEXT, "sem_open");
94+
if (!original_sem_open) {
95+
debug("could not find sem_open in libc");
96+
return SEM_FAILED;
97+
}
98+
dlerror();
99+
}
100+
101+
// mode and value must be set with O_CREAT
102+
va_list argp;
103+
va_start(argp, oflag);
104+
if (oflag & O_CREAT) {
105+
mode = va_arg(argp, mode_t);
106+
value = va_arg(argp, unsigned int);
107+
if (value > SEM_VALUE_MAX) {
108+
errno = EINVAL;
109+
return SEM_FAILED;
110+
}
111+
}
112+
va_end(argp);
113+
114+
const char *snapname = get_snap_name();
115+
116+
// just call libc's sem_open() if snapname not set
117+
if (!snapname) {
118+
if (oflag & O_CREAT) {
119+
return original_sem_open(name, oflag, mode, value);
120+
}
121+
return original_sem_open(name, oflag);
122+
}
123+
124+
// Format the rewritten name
125+
char rewritten[MAX_NAME_SIZE+1];
126+
if (rewrite(snapname, name, rewritten, MAX_NAME_SIZE + 1) != 0) {
127+
return SEM_FAILED;
128+
}
129+
debug("rewritten name: %s", rewritten);
130+
131+
if (oflag & O_CREAT) {
132+
// glibc's sem_open with O_CREAT will create a file in /dev/shm
133+
// by creating a tempfile, initializing it, hardlinking it and
134+
// unlinking the tempfile. We:
135+
// 1. create a temporary file in /dev/shm with rewritten path
136+
// as the template and the specified mode
137+
// 2. initializing a sem_t with sem_init
138+
// 3. writing the initialized sem_t to the temporary file using
139+
// sem_open()s declared value. We used '1' for pshared since
140+
// that is how glibc sets up a named semaphore
141+
// 4. close the temporary file
142+
// 5. hard link the temporary file to the rewritten path. If
143+
// O_EXCL is not specified, ignore EEXIST and just cleanup
144+
// as per documented behavior in 'man sem_open'. If O_EXCL
145+
// is specified and file exists, exit with error. If link is
146+
// successful, cleanup.
147+
// 6. call glibc's sem_open() without O_CREAT|O_EXCL
148+
//
149+
// See glibc's fbtl/sem_open.c for more details
150+
151+
// First, calculate the requested path
152+
char path[PATH_MAX] = { 0 };
153+
// /sem. + '/0' = 14
154+
int max_path_size = strlen(SHM_DIR) + strlen(rewritten) + 6;
155+
if (max_path_size >= PATH_MAX) {
156+
// Should never happen since PATH_MAX should be much
157+
// larger than NAME_MAX, but be defensive.
158+
errno = ENAMETOOLONG;
159+
return SEM_FAILED;
160+
}
161+
int n = snprintf(path, max_path_size, "%s/sem.%s", SHM_DIR,
162+
rewritten);
163+
if (n < 0 || n >= max_path_size) {
164+
errno = ENAMETOOLONG;
165+
return SEM_FAILED;
166+
}
167+
path[max_path_size-1] = '\0';
168+
169+
// Then calculate the template path
170+
char tmp[PATH_MAX] = { 0 };
171+
n = snprintf(tmp, PATH_MAX, "%s/%s.XXXXXX", SHM_DIR,
172+
rewritten);
173+
if (n < 0 || n >= PATH_MAX) {
174+
errno = ENAMETOOLONG;
175+
return SEM_FAILED;
176+
}
177+
tmp[PATH_MAX-1] = '\0';
178+
179+
// Next, create a temporary file
180+
int fd = mkstemp(tmp);
181+
if (fd < 0) {
182+
return SEM_FAILED;
183+
}
184+
debug("tmp name: %s", tmp);
185+
186+
// Update the temporary file to have the requested mode
187+
if (fchmod(fd, mode) < 0) {
188+
close(fd);
189+
unlink(tmp);
190+
return SEM_FAILED;
191+
}
192+
193+
// Then write out an empty semaphore and set the initial value.
194+
// We use '1' for pshared since that is how glibc sets up the
195+
// semaphore (see glibc's fbtl/sem_open.c)
196+
sem_t initsem;
197+
sem_init(&initsem, 1, value);
198+
if (write(fd, &initsem, sizeof(sem_t)) < 0) {
199+
close(fd);
200+
unlink(tmp);
201+
return SEM_FAILED;
202+
}
203+
close(fd);
204+
205+
// Then link the file into place. If the target exists and
206+
// O_EXCL was not specified, just cleanup and proceed to open
207+
// the existing file as per documented behavior in 'man
208+
// sem_open'.
209+
int existed = 0;
210+
if (link(tmp, path) < 0) {
211+
// Note: snapd initially didn't allow 'l' in its
212+
// policy so we first try with link() since it is
213+
// race-free but fallback to rename() if necessary.
214+
if (errno == EACCES || errno == EPERM) {
215+
fprintf(stderr, "sem_open() wrapper: hard linking tempfile denied. Falling back to rename()\n");
216+
if (rename(tmp, path) < 0) {
217+
unlink(tmp);
218+
return SEM_FAILED;
219+
}
220+
} else if (oflag & O_EXCL || errno != EEXIST) {
221+
unlink(tmp);
222+
return SEM_FAILED;
223+
}
224+
existed = 1;
225+
}
226+
unlink(tmp);
227+
228+
// Then call sem_open() on the created file, stripping out the
229+
// O_CREAT|O_EXCL since we just created it
230+
sem_t *sem = original_sem_open(rewritten,
231+
oflag & ~(O_CREAT | O_EXCL));
232+
if (sem == SEM_FAILED) {
233+
if (!existed) {
234+
unlink(path);
235+
}
236+
return SEM_FAILED;
237+
}
238+
239+
return sem;
240+
} else {
241+
// without O_CREAT, just call sem_open with rewritten
242+
return original_sem_open(rewritten, oflag);
243+
}
244+
245+
return SEM_FAILED;
246+
}
247+
248+
// sem_unlink
249+
int sem_unlink(const char *name)
250+
{
251+
debug("sem_unlink()");
252+
debug("requested name: %s", name);
253+
254+
// lookup the libc's sem_unlink() if we haven't already
255+
if (!original_sem_unlink) {
256+
dlerror();
257+
original_sem_unlink = dlsym(RTLD_NEXT, "sem_unlink");
258+
if (!original_sem_unlink) {
259+
debug("could not find sem_unlink in libc");
260+
return -1;
261+
}
262+
dlerror();
263+
}
264+
265+
const char *snapname = get_snap_name();
266+
267+
// just call libc's sem_unlink() if snapname not set
268+
if (!snapname) {
269+
return original_sem_unlink(name);
270+
}
271+
272+
// Format the rewritten name
273+
char rewritten[MAX_NAME_SIZE+1];
274+
if (rewrite(snapname, name, rewritten, MAX_NAME_SIZE + 1) != 0) {
275+
return -1;
276+
}
277+
debug("rewritten name: %s", rewritten);
278+
279+
return original_sem_unlink(rewritten);
280+
}

0 commit comments

Comments
 (0)