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 39400
vjn_init(char **args)
54
{
55 39400
        if (args != NULL && *args != NULL)
56 0
                ARGV_ERR("-jnone takes no arguments.\n");
57 39400
        return (0);
58
}
59
60
static void v_matchproto_(jail_master_f)
61 2406014
vjn_master(enum jail_master_e jme)
62
{
63 2406014
        (void)jme;
64 2406014
}
65
66
static void v_matchproto_(jail_subproc_f)
67 193673
vjn_subproc(enum jail_subproc_e jse)
68
{
69 193673
        (void)jse;
70 193673
}
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 40200
VJ_Init(const char *j_arg)
98
{
99
        char **av;
100
        int i;
101
102 40200
        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 79200
                for (i = 0; vj_choice[i].name != NULL; i++) {
120 79200
                        vjt = vj_choice[i].ptr;
121 79200
                        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
122 79200
                        if (!vjt->init(NULL))
123 39800
                                break;
124 39400
                }
125
        }
126 40200
        VSB_printf(vident, ",-j%s", vjt->name);
127 40200
}
128
129
void
130 2434854
VJ_master(enum jail_master_e jme)
131
{
132 2434854
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
133 2434854
        vjt->master(jme);
134 2434854
}
135
136
void
137 194793
VJ_subproc(enum jail_subproc_e jse)
138
{
139 194793
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
140 194793
        vjt->subproc(jse);
141 194793
}
142
143
int
144 38440
VJ_make_workdir(const char *dname, struct vsb *vsb)
145
{
146
        int i;
147
148 38440
        AN(dname);
149 38440
        AN(vsb);
150 38440
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
151
152 38440
        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 37880
                VJ_master(JAIL_MASTER_FILE);
159 37880
                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 38440
        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 38440
        i = open("_.testfile", O_RDWR|O_CREAT|O_EXCL, 0600);
174 38440
        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 38440
        closefd(&i);
195 38440
        AZ(unlink("_.testfile"));
196 38440
        VJ_master(JAIL_MASTER_LOW);
197 38440
        return (0);
198 38440
}
199
200
int
201 137440
VJ_make_subdir(const char *dname, const char *what, struct vsb *vsb)
202
{
203
        int e;
204
205 137440
        AN(dname);
206 137440
        AN(what);
207 137440
        AN(vsb);
208 137440
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
209 137440
        if (vjt->make_subdir != NULL)
210 1680
                return (vjt->make_subdir(dname, what, vsb));
211
212 135760
        VJ_master(JAIL_MASTER_FILE);
213 135760
        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 135760
        VJ_master(JAIL_MASTER_LOW);
220 135760
        return (0);
221 137440
}
222
223
void
224 132440
VJ_unlink(const char *fname, int ignore_enoent)
225
{
226 132440
        VJ_master(JAIL_MASTER_FILE);
227 132440
        if (unlink(fname)) {
228 11640
                if (errno != ENOENT || !ignore_enoent)
229 0
                    fprintf(stderr, "Could not delete '%s': %s\n",
230 0
                        fname, strerror(errno));
231 11640
        }
232 132440
        VJ_master(JAIL_MASTER_LOW);
233 132440
}
234
235
void
236 12280
VJ_rmdir(const char *dname)
237
{
238 12280
        VJ_master(JAIL_MASTER_FILE);
239 12280
        if (rmdir(dname)) {
240 80
                fprintf(stderr, "Could not rmdir '%s': %s\n",
241 40
                    dname, strerror(errno));
242 40
        }
243 12280
        VJ_master(JAIL_MASTER_LOW);
244 12280
}
245
246
void
247 116360
VJ_fix_fd(int fd, enum jail_fixfd_e what)
248
{
249
250 116360
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
251 116360
        if (vjt->fixfd != NULL)
252 1800
                vjt->fixfd(fd, what);
253 116360
}