diff options
Diffstat (limited to 'openbsd-compat/port-linux.c')
-rw-r--r-- | openbsd-compat/port-linux.c | 140 |
1 files changed, 91 insertions, 49 deletions
diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c index 9cb58e369..c0ac9065e 100644 --- a/openbsd-compat/port-linux.c +++ b/openbsd-compat/port-linux.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: port-linux.c,v 1.5 2008/03/26 20:27:21 dtucker Exp $ */ | 1 | /* $Id: port-linux.c,v 1.8 2010/03/01 04:52:50 dtucker Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com> | 4 | * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com> |
@@ -18,33 +18,28 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | /* | 20 | /* |
21 | * Linux-specific portability code | 21 | * Linux-specific portability code - just SELinux support at present |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "includes.h" | 24 | #include "includes.h" |
25 | 25 | ||
26 | #if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST) | ||
26 | #include <errno.h> | 27 | #include <errno.h> |
27 | #include <stdarg.h> | 28 | #include <stdarg.h> |
28 | #include <string.h> | 29 | #include <string.h> |
29 | 30 | #include <stdio.h> | |
30 | #ifdef OOM_ADJUST | ||
31 | #include <sys/types.h> | ||
32 | #include <sys/stat.h> | ||
33 | #include <fcntl.h> | ||
34 | #include <unistd.h> | ||
35 | #endif | ||
36 | |||
37 | #include "log.h" | ||
38 | 31 | ||
39 | #ifdef WITH_SELINUX | 32 | #ifdef WITH_SELINUX |
40 | #include "key.h" | 33 | #include "key.h" |
41 | #include "hostfile.h" | 34 | #include "hostfile.h" |
42 | #include "auth.h" | 35 | #include "auth.h" |
43 | #ifdef HAVE_GETSEUSERBYNAME | ||
44 | #include "xmalloc.h" | ||
45 | #endif | 36 | #endif |
37 | |||
38 | #include "log.h" | ||
39 | #include "xmalloc.h" | ||
46 | #include "port-linux.h" | 40 | #include "port-linux.h" |
47 | 41 | ||
42 | #ifdef WITH_SELINUX | ||
48 | #include <selinux/selinux.h> | 43 | #include <selinux/selinux.h> |
49 | #include <selinux/flask.h> | 44 | #include <selinux/flask.h> |
50 | #include <selinux/get_context_list.h> | 45 | #include <selinux/get_context_list.h> |
@@ -193,48 +188,95 @@ ssh_selinux_setup_pty(char *pwname, const char *tty) | |||
193 | freecon(user_ctx); | 188 | freecon(user_ctx); |
194 | debug3("%s: done", __func__); | 189 | debug3("%s: done", __func__); |
195 | } | 190 | } |
196 | #endif /* WITH_SELINUX */ | ||
197 | 191 | ||
198 | #ifdef OOM_ADJUST | 192 | void |
199 | /* Get the out-of-memory adjustment file for the current process */ | 193 | ssh_selinux_change_context(const char *newname) |
200 | static int | ||
201 | oom_adj_open(int oflag) | ||
202 | { | 194 | { |
203 | int fd = open("/proc/self/oom_adj", oflag); | 195 | int len, newlen; |
204 | if (fd < 0) | 196 | char *oldctx, *newctx, *cx; |
205 | logit("error opening /proc/self/oom_adj: %s", strerror(errno)); | 197 | |
206 | return fd; | 198 | if (!ssh_selinux_enabled()) |
199 | return; | ||
200 | |||
201 | if (getcon((security_context_t *)&oldctx) < 0) { | ||
202 | logit("%s: getcon failed with %s", __func__, strerror (errno)); | ||
203 | return; | ||
204 | } | ||
205 | if ((cx = index(oldctx, ':')) == NULL || (cx = index(cx + 1, ':')) == | ||
206 | NULL) { | ||
207 | logit ("%s: unparseable context %s", __func__, oldctx); | ||
208 | return; | ||
209 | } | ||
210 | |||
211 | newlen = strlen(oldctx) + strlen(newname) + 1; | ||
212 | newctx = xmalloc(newlen); | ||
213 | len = cx - oldctx + 1; | ||
214 | memcpy(newctx, oldctx, len); | ||
215 | strlcpy(newctx + len, newname, newlen - len); | ||
216 | if ((cx = index(cx + 1, ':'))) | ||
217 | strlcat(newctx, cx, newlen); | ||
218 | debug3("%s: setting context from '%s' to '%s'", __func__, oldctx, | ||
219 | newctx); | ||
220 | if (setcon(newctx) < 0) | ||
221 | logit("%s: setcon failed with %s", __func__, strerror (errno)); | ||
222 | xfree(oldctx); | ||
223 | xfree(newctx); | ||
207 | } | 224 | } |
225 | #endif /* WITH_SELINUX */ | ||
208 | 226 | ||
209 | /* Get the current OOM adjustment */ | 227 | #ifdef LINUX_OOM_ADJUST |
210 | int | 228 | #define OOM_ADJ_PATH "/proc/self/oom_adj" |
211 | oom_adj_get(char *buf, size_t maxlen) | 229 | /* |
230 | * The magic "don't kill me", as documented in eg: | ||
231 | * http://lxr.linux.no/#linux+v2.6.32/Documentation/filesystems/proc.txt | ||
232 | */ | ||
233 | #define OOM_ADJ_NOKILL -17 | ||
234 | |||
235 | static int oom_adj_save = INT_MIN; | ||
236 | |||
237 | /* | ||
238 | * Tell the kernel's out-of-memory killer to avoid sshd. | ||
239 | * Returns the previous oom_adj value or zero. | ||
240 | */ | ||
241 | void | ||
242 | oom_adjust_setup(void) | ||
212 | { | 243 | { |
213 | ssize_t n; | 244 | FILE *fp; |
214 | int fd = oom_adj_open(O_RDONLY); | 245 | |
215 | if (fd < 0) | 246 | debug3("%s", __func__); |
216 | return -1; | 247 | if ((fp = fopen(OOM_ADJ_PATH, "r+")) != NULL) { |
217 | n = read(fd, buf, maxlen); | 248 | if (fscanf(fp, "%d", &oom_adj_save) != 1) |
218 | if (n < 0) | 249 | verbose("error reading %s: %s", OOM_ADJ_PATH, strerror(errno)); |
219 | logit("error reading /proc/self/oom_adj: %s", strerror(errno)); | 250 | else { |
220 | else | 251 | rewind(fp); |
221 | buf[n] = '\0'; | 252 | if (fprintf(fp, "%d\n", OOM_ADJ_NOKILL) <= 0) |
222 | close(fd); | 253 | verbose("error writing %s: %s", |
223 | return n < 0 ? -1 : 0; | 254 | OOM_ADJ_PATH, strerror(errno)); |
255 | else | ||
256 | verbose("Set %s from %d to %d", | ||
257 | OOM_ADJ_PATH, oom_adj_save, OOM_ADJ_NOKILL); | ||
258 | } | ||
259 | fclose(fp); | ||
260 | } | ||
224 | } | 261 | } |
225 | 262 | ||
226 | /* Set the current OOM adjustment */ | 263 | /* Restore the saved OOM adjustment */ |
227 | int | 264 | void |
228 | oom_adj_set(const char *buf) | 265 | oom_adjust_restore(void) |
229 | { | 266 | { |
230 | ssize_t n; | 267 | FILE *fp; |
231 | int fd = oom_adj_open(O_WRONLY); | 268 | |
232 | if (fd < 0) | 269 | debug3("%s", __func__); |
233 | return -1; | 270 | if (oom_adj_save == INT_MIN || (fp = fopen(OOM_ADJ_PATH, "w")) == NULL) |
234 | n = write(fd, buf, strlen(buf)); | 271 | return; |
235 | if (n < 0) | 272 | |
236 | logit("error writing /proc/self/oom_adj: %s", strerror(errno)); | 273 | if (fprintf(fp, "%d\n", oom_adj_save) <= 0) |
237 | close(fd); | 274 | verbose("error writing %s: %s", OOM_ADJ_PATH, strerror(errno)); |
238 | return n < 0 ? -1 : 0; | 275 | else |
276 | verbose("Set %s to %d", OOM_ADJ_PATH, oom_adj_save); | ||
277 | |||
278 | fclose(fp); | ||
279 | return; | ||
239 | } | 280 | } |
240 | #endif | 281 | #endif /* LINUX_OOM_ADJUST */ |
282 | #endif /* WITH_SELINUX || LINUX_OOM_ADJUST */ | ||