-
Notifications
You must be signed in to change notification settings - Fork 3
/
nshold.c
120 lines (105 loc) · 2.9 KB
/
nshold.c
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
111
112
113
114
115
116
117
118
119
120
/*
* nsutils: namespace utilities
* Copyright (C) 2016 Renzo Davoli, University of Bologna
*
* nshold: keep-alive and give a name tag to a namespace
*
* Cado is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <errno.h>
#include <limits.h>
#include <unistd.h>
#include <sys/capability.h>
#include <catargv.h>
#include <prefix.h>
#define NAMELEN (strlen(basename(__FILE__)) - 2)
#define NSPATH "/proc/self/ns/"
int clear_all_caps(void) {
cap_t caps=cap_get_proc();
cap_clear_flag(caps, CAP_EFFECTIVE);
cap_clear_flag(caps, CAP_INHERITABLE);
cap_clear_flag(caps, CAP_PERMITTED);
return cap_set_proc(caps);
}
/* read a symlink and return a strdup of the link target */
static char *readlinkdup(char *pathname) {
char buf[PATH_MAX + 1];
ssize_t len = readlink(pathname, buf, PATH_MAX);
if (len < 0)
return NULL;
buf[len] = 0;
return strdup(buf);
}
int dashdashargc(char **argv) {
int i;
for (i = 1; argv[i]; i++) {
if (strcmp(argv[i], "--") == 0)
return i;
}
return i;
}
void usage_and_exit(char *progname, char *prefix) {
fprintf(stderr, "Usage:\n"
"\t%s [placeholder_tag]\n"
"or\n"
"\t%s -- long placeholder tag\n\n", progname, progname);
exit (1);
}
/* create a placeholder process for the namespace */
int main(int argc, char **argv, char **envp)
{
if (guessprefix(argv[0]) == NULL) {
char *progname = basename(argv[0]);
int prefixlen = strlen(progname) - NAMELEN;
char *prefix = NULL;
char *nspath;
char *nsname;
int dashdash = dashdashargc(argv);
char *tag = NULL;
if (prefixlen == 0)
prefixerror_and_exit(progname);
else
asprintf(&prefix, "%.*s", prefixlen, progname);
if (dashdash < argc)
tag = catargv(argv+(dashdash + 1));
else if (argc == 2) {
if (argv[1][0] == '-')
usage_and_exit(progname, prefix);
else
tag = argv[1];
} else if (argc != 1)
usage_and_exit(progname, prefix);
clear_all_caps();
asprintf(&nspath, "%s%.*s", NSPATH, prefixlen, basename(argv[0]));
if ((nsname = readlinkdup(nspath)) == NULL)
return 1;
static char *newargv[2];
if (tag && *tag)
asprintf(&newargv[0],"%s %s", nsname, tag);
else
asprintf(&newargv[0],"%s", nsname);
daemon(0,0);
execve("/proc/self/exe", newargv, envp);
return 1;
} else {
while (1)
pause();
return 0;
}
}