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 39000
vjn_init(char **args)
54
{
55 39000
        if (args != NULL && *args != NULL)
56 0
                ARGV_ERR("-jnone takes no arguments.\n");
57 39000
        return (0);
58
}
59
60
static void v_matchproto_(jail_master_f)
61 2379566
vjn_master(enum jail_master_e jme)
62
{
63 2379566
        (void)jme;
64 2379566
}
65
66
static void v_matchproto_(jail_subproc_f)
67 191470
vjn_subproc(enum jail_subproc_e jse)
68
{
69 191470
        (void)jse;
70 191470
}
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 39760
VJ_Init(const char *j_arg)
98
{
99
        char **av;
100
        int i;
101
102 39760
        if (j_arg != NULL) {
103 360
                av = VAV_Parse(j_arg, NULL, ARGV_COMMA);
104 360
                AN(av);
105 360
                if (av[0] != NULL)
106 0
                        ARGV_ERR("-j argument: %s\n", av[0]);
107 360
                if (av[1] == NULL)
108 0
                        ARGV_ERR("-j argument is empty\n");
109 360
                vjt = MGT_Pick(vj_choice, av[1], "jail");
110 360
                CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
111 360
                (void)vjt->init(av + 2);
112 360
                VAV_Free(av);
113 360
        } else {
114
                /*
115
                 * Go through list of jail technologies until one
116
                 * succeeds, falling back to "none".
117
                 */
118 78400
                for (i = 0; vj_choice[i].name != NULL; i++) {
119 78400
                        vjt = vj_choice[i].ptr;
120 78400
                        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
121 78400
                        if (!vjt->init(NULL))
122 39400
                                break;
123 39000
                }
124
        }
125 39760
        VSB_printf(vident, ",-j%s", vjt->name);
126 39760
}
127
128
void
129 2408406
VJ_master(enum jail_master_e jme)
130
{
131 2408406
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
132 2408406
        vjt->master(jme);
133 2408406
}
134
135
void
136 192590
VJ_subproc(enum jail_subproc_e jse)
137
{
138 192590
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
139 192590
        vjt->subproc(jse);
140 192590
}
141
142
int
143 38040
VJ_make_workdir(const char *dname)
144
{
145
        int i;
146
147 38040
        AN(dname);
148 38040
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
149 38040
        if (vjt->make_workdir != NULL) {
150 560
                i = vjt->make_workdir(dname, NULL, NULL);
151 560
                if (i)
152 0
                        return (i);
153 560
                VJ_master(JAIL_MASTER_FILE);
154 560
        } else {
155 37480
                VJ_master(JAIL_MASTER_FILE);
156 37480
                if (mkdir(dname, 0755) < 0 && errno != EEXIST)
157 0
                        ARGV_ERR("Cannot create working directory '%s': %s\n",
158
                                 dname, VAS_errtxt(errno));
159
        }
160
161 38040
        if (chdir(dname) < 0)
162 0
                ARGV_ERR("Cannot change to working directory '%s': %s\n",
163
                    dname, VAS_errtxt(errno));
164
165 38040
        i = open("_.testfile", O_RDWR|O_CREAT|O_EXCL, 0600);
166 38040
        if (i < 0)
167 0
                ARGV_ERR("Cannot create test-file in %s (%s)\n"
168
                    "Check permissions (or delete old directory)\n",
169
                    dname, VAS_errtxt(errno));
170
171
#ifdef ST_NOEXEC
172
        struct statvfs vfs[1];
173
174
        /* deliberately ignore fstatvfs errors */
175
        if (! fstatvfs(i, vfs) && vfs->f_flag & ST_NOEXEC) {
176
                closefd(&i);
177
                AZ(unlink("_.testfile"));
178
                ARGV_ERR("Working directory %s (-n argument) "
179
                    "cannot reside on a file system mounted noexec\n", dname);
180
        }
181
#endif
182
183 38040
        closefd(&i);
184 38040
        AZ(unlink("_.testfile"));
185 38040
        VJ_master(JAIL_MASTER_LOW);
186 38040
        return (0);
187 38040
}
188
189
int
190 136000
VJ_make_subdir(const char *dname, const char *what, struct vsb *vsb)
191
{
192
        int e;
193
194 136000
        AN(dname);
195 136000
        AN(what);
196 136000
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
197 136000
        if (vjt->make_subdir != NULL)
198 1680
                return (vjt->make_subdir(dname, what, vsb));
199
200 134320
        VJ_master(JAIL_MASTER_FILE);
201 134320
        if (mkdir(dname, 0755) < 0 && errno != EEXIST) {
202 0
                e = errno;
203 0
                if (vsb != NULL) {
204 0
                        VSB_printf(vsb,
205
                            "Cannot create %s directory '%s': %s\n",
206 0
                            what, dname, VAS_errtxt(e));
207 0
                } else {
208 0
                        MGT_Complain(C_ERR,
209
                            "Cannot create %s directory '%s': %s",
210 0
                            what, dname, VAS_errtxt(e));
211
                }
212 0
                return (1);
213
        }
214 134320
        VJ_master(JAIL_MASTER_LOW);
215 134320
        return (0);
216 136000
}
217
218
void
219 131040
VJ_unlink(const char *fname, int ignore_enoent)
220
{
221 131040
        VJ_master(JAIL_MASTER_FILE);
222 131040
        if (unlink(fname)) {
223 11520
                if (errno != ENOENT || !ignore_enoent)
224 0
                    fprintf(stderr, "Could not delete '%s': %s\n",
225 0
                        fname, strerror(errno));
226 11520
        }
227 131040
        VJ_master(JAIL_MASTER_LOW);
228 131040
}
229
230
void
231 12160
VJ_rmdir(const char *dname)
232
{
233 12160
        VJ_master(JAIL_MASTER_FILE);
234 12160
        if (rmdir(dname)) {
235 80
                fprintf(stderr, "Could not rmdir '%s': %s\n",
236 40
                    dname, strerror(errno));
237 40
        }
238 12160
        VJ_master(JAIL_MASTER_LOW);
239 12160
}
240
241
void
242 115040
VJ_fix_fd(int fd, enum jail_fixfd_e what)
243
{
244
245 115040
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
246 115040
        if (vjt->fixfd != NULL)
247 1800
                vjt->fixfd(fd, what);
248 115040
}