varnish-cache/bin/varnishd/mgt/mgt_jail.c
0
/*-
1
 * Copyright (c) 2015 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 * Jailing
30
 *
31
 */
32
33
#include "config.h"
34
35
#include <fcntl.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <unistd.h>
40
#include <sys/stat.h>
41
//lint -efile(766, sys/statvfs.h)
42
#include <sys/statvfs.h>
43
44
#include "mgt/mgt.h"
45
#include "common/heritage.h"
46
#include "vav.h"
47
48
/**********************************************************************
49
 * A "none" jail implementation which doesn't do anything.
50
 */
51
52
static int v_matchproto_(jail_init_f)
53 39760
vjn_init(char **args)
54
{
55 39760
        if (args != NULL && *args != NULL)
56 0
                ARGV_ERR("-jnone takes no arguments.\n");
57 39760
        return (0);
58
}
59
60
static void v_matchproto_(jail_master_f)
61 2427646
vjn_master(enum jail_master_e jme)
62
{
63 2427646
        (void)jme;
64 2427646
}
65
66
static void v_matchproto_(jail_subproc_f)
67 195271
vjn_subproc(enum jail_subproc_e jse)
68
{
69 195271
        (void)jse;
70 195271
}
71
72
static const struct jail_tech jail_tech_none = {
73
        .magic =        JAIL_TECH_MAGIC,
74
        .name =         "none",
75
        .init =         vjn_init,
76
        .master =       vjn_master,
77
        .subproc =      vjn_subproc,
78
};
79
80
/**********************************************************************/
81
82
static const struct jail_tech *vjt;
83
84
static const struct choice vj_choice[] = {
85
#ifdef HAVE_SETPPRIV
86
        { "solaris",    &jail_tech_solaris },
87
#endif
88
#ifdef __linux__
89
        { "linux",      &jail_tech_linux },
90
#endif
91
        { "unix",       &jail_tech_unix },
92
        { "none",       &jail_tech_none },
93
        { NULL,         NULL },
94
};
95
96
void
97 40560
VJ_Init(const char *j_arg)
98
{
99
        char **av;
100
        int i;
101
102 40560
        if (j_arg != NULL) {
103 400
                av = VAV_Parse(j_arg, NULL, ARGV_COMMA);
104 400
                AN(av);
105 400
                if (av[0] != NULL)
106 0
                        ARGV_ERR("-j argument: %s\n", av[0]);
107 400
                if (av[1] == NULL)
108 0
                        ARGV_ERR("-j argument is empty\n");
109 400
                vjt = MGT_Pick(vj_choice, av[1], "jail");
110 400
                CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
111 400
                if (vjt->init(av + 2))
112 0
                        ARGV_EXIT;
113 400
                VAV_Free(av);
114 400
        } else {
115
                /*
116
                 * Go through list of jail technologies until one
117
                 * succeeds, falling back to "none".
118
                 */
119 79920
                for (i = 0; vj_choice[i].name != NULL; i++) {
120 79920
                        vjt = vj_choice[i].ptr;
121 79920
                        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
122 79920
                        if (!vjt->init(NULL))
123 40160
                                break;
124 39760
                }
125
        }
126 40560
        VSB_printf(vident, ",-j%s", vjt->name);
127 40560
}
128
129
void
130 2456486
VJ_master(enum jail_master_e jme)
131
{
132 2456486
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
133 2456486
        vjt->master(jme);
134 2456486
}
135
136
void
137 196391
VJ_subproc(enum jail_subproc_e jse)
138
{
139 196391
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
140 196391
        vjt->subproc(jse);
141 196391
}
142
143
int
144 38800
VJ_make_workdir(const char *dname, struct vsb *vsb)
145
{
146
        int i;
147
148 38800
        AN(dname);
149 38800
        AN(vsb);
150 38800
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
151
152 38800
        if (vjt->make_workdir != NULL) {
153 560
                i = vjt->make_workdir(dname, NULL, vsb);
154 560
                if (i)
155 0
                        return (i);
156 560
                VJ_master(JAIL_MASTER_FILE);
157 560
        } else {
158 38240
                VJ_master(JAIL_MASTER_FILE);
159 38240
                if (mkdir(dname, 0755) < 0 && errno != EEXIST) {
160 0
                        VSB_printf(vsb,
161
                            "Cannot create working directory '%s': %s\n",
162 0
                            dname, VAS_errtxt(errno));
163 0
                        return (1);
164
                }
165
        }
166
167 38800
        if (chdir(dname) < 0) {
168 0
                VSB_printf(vsb, "Cannot change to working directory '%s': %s\n",
169 0
                    dname, VAS_errtxt(errno));
170 0
                return (1);
171
        }
172
173 38800
        i = open("_.testfile", O_RDWR|O_CREAT|O_EXCL, 0600);
174 38800
        if (i < 0) {
175 0
                VSB_printf(vsb, "Cannot create test-file in %s (%s)\n"
176
                    "Check permissions (or delete old directory)\n",
177 0
                    dname, VAS_errtxt(errno));
178 0
                return (1);
179
        }
180
181
#ifdef ST_NOEXEC
182
        struct statvfs vfs[1];
183
184
        /* deliberately ignore fstatvfs errors */
185
        if (! fstatvfs(i, vfs) && vfs->f_flag & ST_NOEXEC) {
186
                closefd(&i);
187
                AZ(unlink("_.testfile"));
188
                VSB_printf(vsb, "Working directory %s (-n argument) "
189
                    "cannot reside on a file system mounted noexec\n", dname);
190
                return (1);
191
        }
192
#endif
193
194 38800
        closefd(&i);
195 38800
        AZ(unlink("_.testfile"));
196 38800
        VJ_master(JAIL_MASTER_LOW);
197 38800
        return (0);
198 38800
}
199
200
int
201 138640
VJ_make_subdir(const char *dname, const char *what, struct vsb *vsb)
202
{
203
        int e;
204
205 138640
        AN(dname);
206 138640
        AN(what);
207 138640
        AN(vsb);
208 138640
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
209 138640
        if (vjt->make_subdir != NULL)
210 1680
                return (vjt->make_subdir(dname, what, vsb));
211
212 136960
        VJ_master(JAIL_MASTER_FILE);
213 136960
        if (mkdir(dname, 0755) < 0 && errno != EEXIST) {
214 0
                e = errno;
215 0
                VSB_printf(vsb, "Cannot create %s directory '%s': %s\n",
216 0
                    what, dname, VAS_errtxt(e));
217 0
                return (1);
218
        }
219 136960
        VJ_master(JAIL_MASTER_LOW);
220 136960
        return (0);
221 138640
}
222
223
void
224 133440
VJ_unlink(const char *fname, int ignore_enoent)
225
{
226 133440
        VJ_master(JAIL_MASTER_FILE);
227 133440
        if (unlink(fname)) {
228 11680
                if (errno != ENOENT || !ignore_enoent)
229 0
                    fprintf(stderr, "Could not delete '%s': %s\n",
230 0
                        fname, strerror(errno));
231 11680
        }
232 133440
        VJ_master(JAIL_MASTER_LOW);
233 133440
}
234
235
void
236 12320
VJ_rmdir(const char *dname)
237
{
238 12320
        VJ_master(JAIL_MASTER_FILE);
239 12320
        if (rmdir(dname)) {
240 80
                fprintf(stderr, "Could not rmdir '%s': %s\n",
241 40
                    dname, strerror(errno));
242 40
        }
243 12320
        VJ_master(JAIL_MASTER_LOW);
244 12320
}
245
246
void
247 117440
VJ_fix_fd(int fd, enum jail_fixfd_e what)
248
{
249
250 117440
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
251 117440
        if (vjt->fixfd != NULL)
252 1800
                vjt->fixfd(fd, what);
253 117440
}