varnish-cache/bin/varnishd/mgt/mgt_jail.c
1
/*-
2
 * Copyright (c) 2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 *
28
 * Jailing
29
 *
30
 */
31
32
#include "config.h"
33
34
#include <fcntl.h>
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38
#include <unistd.h>
39
#include <sys/stat.h>
40
41
#include "mgt/mgt.h"
42
#include "common/heritage.h"
43
#include "vav.h"
44
45
/**********************************************************************
46
 * A "none" jail implementation which doesn't do anything.
47
 */
48
49
static int v_matchproto_(jail_init_f)
50 14022
vjn_init(char **args)
51
{
52 14022
        if (args != NULL && *args != NULL)
53 0
                ARGV_ERR("-jnone takes no arguments.\n");
54 14022
        return (0);
55
}
56
57
static void v_matchproto_(jail_master_f)
58 378468
vjn_master(enum jail_master_e jme)
59
{
60 378468
        (void)jme;
61 378468
}
62
63
static void v_matchproto_(jail_subproc_f)
64 66348
vjn_subproc(enum jail_subproc_e jse)
65
{
66 66348
        (void)jse;
67 66348
}
68
69
static const struct jail_tech jail_tech_none = {
70
        .magic =        JAIL_TECH_MAGIC,
71
        .name =         "none",
72
        .init =         vjn_init,
73
        .master =       vjn_master,
74
        .subproc =      vjn_subproc,
75
};
76
77
/**********************************************************************/
78
79
static const struct jail_tech *vjt;
80
81
static const struct choice vj_choice[] = {
82
#ifdef HAVE_SETPPRIV
83
        { "solaris",    &jail_tech_solaris },
84
#endif
85
        { "unix",       &jail_tech_unix },
86
        { "none",       &jail_tech_none },
87
        { NULL,         NULL },
88
};
89
90
void
91 14382
VJ_Init(const char *j_arg)
92
{
93
        char **av;
94
        int i;
95
96 14382
        if (j_arg != NULL) {
97 180
                av = VAV_Parse(j_arg, NULL, ARGV_COMMA);
98 180
                AN(av);
99 180
                if (av[0] != NULL)
100 0
                        ARGV_ERR("-j argument: %s\n", av[0]);
101 180
                if (av[1] == NULL)
102 0
                        ARGV_ERR("-j argument is emtpy\n");
103 180
                vjt = MGT_Pick(vj_choice, av[1], "jail");
104 180
                CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
105 162
                (void)vjt->init(av + 2);
106 162
                VAV_Free(av);
107 162
        } else {
108
                /*
109
                 * Go through list of jail technologies until one
110
                 * succeeds, falling back to "none".
111
                 */
112 28224
                for (i = 0; vj_choice[i].name != NULL; i++) {
113 28224
                        vjt = vj_choice[i].ptr;
114 28224
                        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
115 28224
                        if (!vjt->init(NULL))
116 14202
                                break;
117 14022
                }
118
        }
119 14274
        VSB_printf(vident, ",-j%s", vjt->name);
120 14274
}
121
122
void
123 385776
VJ_master(enum jail_master_e jme)
124
{
125 385776
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
126 385776
        vjt->master(jme);
127 385776
}
128
129
void
130 66852
VJ_subproc(enum jail_subproc_e jse)
131
{
132 66852
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
133 66852
        vjt->subproc(jse);
134 66852
}
135
136
int
137 13518
VJ_make_workdir(const char *dname)
138
{
139
        int i;
140
141 13518
        AN(dname);
142 13518
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
143 13518
        if (vjt->make_workdir != NULL) {
144 252
                i = vjt->make_workdir(dname, NULL, NULL);
145 252
                if (i)
146 0
                        return (i);
147 252
                VJ_master(JAIL_MASTER_FILE);
148 252
        } else {
149 13266
                VJ_master(JAIL_MASTER_FILE);
150 13266
                if (mkdir(dname, 0755) < 0 && errno != EEXIST)
151 0
                        ARGV_ERR("Cannot create working directory '%s': %s\n",
152
                                 dname, vstrerror(errno));
153
        }
154
155 13518
        if (chdir(dname) < 0)
156 0
                ARGV_ERR("Cannot change to working directory '%s': %s\n",
157
                    dname, vstrerror(errno));
158
159 13518
        i = open("_.testfile", O_RDWR|O_CREAT|O_EXCL, 0600);
160 13518
        if (i < 0)
161 0
                ARGV_ERR("Cannot create test-file in %s (%s)\n"
162
                    "Check permissions (or delete old directory)\n",
163
                    dname, vstrerror(errno));
164 13518
        closefd(&i);
165 13518
        AZ(unlink("_.testfile"));
166 13518
        VJ_master(JAIL_MASTER_LOW);
167 13518
        return (0);
168 13518
}
169
170
int
171 33876
VJ_make_subdir(const char *dname, const char *what, struct vsb *vsb)
172
{
173
        int e;
174
175 33876
        AN(dname);
176 33876
        AN(what);
177 33876
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
178 33876
        if (vjt->make_subdir != NULL)
179 504
                return (vjt->make_subdir(dname, what, vsb));
180
181 33372
        if (mkdir(dname, 0755) < 0 && errno != EEXIST) {
182 0
                e = errno;
183 0
                if (vsb != NULL) {
184 0
                        VSB_printf(vsb,
185
                            "Cannot create %s directory '%s': %s\n",
186 0
                            what, dname, vstrerror(e));
187 0
                } else {
188 0
                        MGT_Complain(C_ERR,
189
                            "Cannot create %s directory '%s': %s",
190 0
                            what, dname, vstrerror(e));
191
                }
192 0
                return (1);
193
        }
194 33372
        return (0);
195 33876
}
196
197
void
198 27216
VJ_fix_fd(int fd, enum jail_fixfd_e what)
199
{
200
201 27216
        CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC);
202 27216
        if (vjt->fixfd != NULL)
203 576
                vjt->fixfd(fd, what);
204 27216
}