diff options
author | Colin Watson <cjwatson@debian.org> | 2011-01-04 11:11:12 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2011-01-04 11:11:12 +0000 |
commit | 3c3c7ee6965eee3f121e2a762dd1c55b54430721 (patch) | |
tree | ef45179c5800382161b1898689779563bf748f69 /src/manconv_client.c | |
parent | 0f4620d4ac262733db798f986aece1ef03796a12 (diff) |
* lib/security.c (running_setuid): New function.
* lib/security.h (running_setuid): Add prototype.
* src/manconv_client.c (manconv_stdin): If running setuid, exec
manconv as an external process, since iconv_open is not guaranteed
to work correctly in setuid processes.
* configure.ac: Require libpipeline >= 1.1.0.
* docs/INSTALL.quick: Document increased version requirement.
* NEWS: Document this.
Diffstat (limited to 'src/manconv_client.c')
-rw-r--r-- | src/manconv_client.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/src/manconv_client.c b/src/manconv_client.c index 7533b14c..b8e7fd8d 100644 --- a/src/manconv_client.c +++ b/src/manconv_client.c @@ -33,6 +33,11 @@ #include "pipeline.h" #include "decompress.h" +#ifdef SECURE_MAN_UID +# include "idpriv.h" +# include "security.h" +#endif /* SECURE_MAN_UID */ + #include "manconv.h" #include "manconv_client.h" @@ -44,8 +49,44 @@ struct manconv_codes { static void manconv_stdin (void *data) { struct manconv_codes *codes = data; - pipeline *p = decompress_fdopen (dup (STDIN_FILENO)); + pipeline *p; + +#ifdef SECURE_MAN_UID + /* iconv_open may not work correctly in setuid processes; in GNU + * libc, gconv modules may be linked against other gconv modules and + * rely on RPATH $ORIGIN to load those modules from the correct + * path, but $ORIGIN is disabled in setuid processes. It is + * impossible to reset libc's idea of setuidness without creating a + * whole new process image. Therefore, if the calling process is + * setuid, we must drop privileges and execute manconv. + * + * If dropping privileges fails, fall through to the in-process + * code, as in some situations it may actually manage to work. + */ + if (running_setuid () && !idpriv_drop ()) { + char **from_code; + char *sources = NULL; + pipecmd *cmd; + + for (from_code = codes->from; *from_code; ++from_code) { + sources = appendstr (sources, *from_code, NULL); + if (*(from_code + 1)) + sources = appendstr (sources, ":", NULL); + } + + cmd = pipecmd_new_args (MANCONV, "-f", sources, + "-t", codes->to, NULL); + free (sources); + + if (quiet >= 2) + pipecmd_arg (cmd, "-q"); + + pipecmd_exec (cmd); + /* never returns */ + } +#endif /* SECURE_MAN_UID */ + p = decompress_fdopen (dup (STDIN_FILENO)); pipeline_start (p); manconv (p, codes->from, codes->to); pipeline_wait (p); |