Commit de9453f4 authored by Joe Clarke's avatar Joe Clarke Committed by David Zeuthen

Bug 23093 – FreeBSD portability fixes

There are a few issues with building polkit-0.93 on FreeBSD:

 * No clearenv() function on FreeBSD

 * While FreeBSD has a /proc, it is deprecated, and kinfo_proc should
   be used instead.

 * FreeBSD's printf() functions do not support the %m notation.  This
   is only supported for syslog().

  * You can't call GINT_TO_POINTER() on a 64-bit value, as this will
    break on 64-bit OSes.

The attached patch fixes these problems.  First, a check for
clearenv() is added to configure.  Second, I moved the check for
process uid to polkit/polkitunixprocess.c.  This may not be ideal, but
it seems to fit, and reduces code duplication.  Third, I replaces all
%m with %s ... g_strerror (errno).  Finally, I replaced
GINT_TO_POINTER() with GSIZE_TO_POINTER.
Signed-off-by: default avatarDavid Zeuthen <davidz@redhat.com>
parent 933e21f1
......@@ -140,6 +140,8 @@ AC_CHECK_LIB(expat,XML_ParserCreate,[EXPAT_LIBS="-lexpat"],
[AC_MSG_ERROR([Can't find expat library. Please install expat.])])
AC_SUBST(EXPAT_LIBS)
AC_CHECK_FUNCS(clearenv)
if test "x$GCC" = "xyes"; then
LDFLAGS="-Wl,--as-needed $LDFLAGS"
fi
......@@ -323,6 +325,8 @@ if test x$with_os_type = x; then
with_os_type=pardus
elif test x$operating_system = xsolaris ; then
with_os_type=solaris
elif test x$operating_system = xfreebsd ; then
with_os_type=freebsd
else
with_os_type=unknown
fi
......
......@@ -21,6 +21,7 @@
#include <glib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
int
......@@ -38,7 +39,7 @@ main (int argc, char *argv[])
if (getcwd (cwd, sizeof cwd) == NULL)
{
g_printerr ("Error getting cwd: %m");
g_printerr ("Error getting cwd: %s", g_strerror (errno));
goto out;
}
......
......@@ -25,6 +25,7 @@
#include <string.h>
#include <grp.h>
#include <errno.h>
#include "polkitunixgroup.h"
#include "polkitidentity.h"
#include "polkiterror.h"
......@@ -210,8 +211,9 @@ polkit_unix_group_new_for_name (const gchar *name,
g_set_error (error,
POLKIT_ERROR,
POLKIT_ERROR_FAILED,
"No UNIX group with name %s: %m",
name);
"No UNIX group with name %s: %s",
name,
g_strerror (errno));
goto out;
}
......
......@@ -23,6 +23,14 @@
# include "config.h"
#endif
#include <sys/types.h>
#ifndef HAVE_FREEBSD
#include <sys/stat.h>
#else
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#endif
#include <stdlib.h>
#include <string.h>
#include "polkitunixprocess.h"
......@@ -72,6 +80,10 @@ static void subject_iface_init (PolkitSubjectIface *subject_iface);
static guint64 get_start_time_for_pid (pid_t pid,
GError **error);
#ifdef HAVE_FREEBSD
static gboolean get_kinfo_proc (pid_t pid, struct kinfo_proc *p);
#endif
G_DEFINE_TYPE_WITH_CODE (PolkitUnixProcess, polkit_unix_process, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (POLKIT_TYPE_SUBJECT, subject_iface_init)
);
......@@ -186,6 +198,44 @@ polkit_unix_process_get_pid (PolkitUnixProcess *process)
return process->pid;
}
/**
* polkit_unix_pid_get_uid:
* @pid: A process ID.
* @uid: A pointer to a uid_t.
*
* Gets the uid for a given @pid.
*
* Returns: 0 on success, -1 on failure.
*/
int
polkit_unix_pid_get_uid (pid_t pid, uid_t *uid)
{
#ifndef HAVE_FREEBSD
struct stat statbuf;
char procbuf[32];
#else
struct kinfo_proc p;
#endif
g_return_val_if_fail (uid != NULL, -1);
g_return_val_if_fail (pid > 0, -1);
#ifndef HAVE_FREEBSD
g_snprintf (procbuf, sizeof procbuf, "/proc/%d", pid);
if (stat (procbuf, &statbuf) != 0)
return -1;
*uid = statbuf.st_uid;
#else
if (! get_kinfo_proc (pid, &p))
return -1;
*uid = p.ki_uid;
#endif
return 0;
}
/**
* polkit_unix_process_get_start_time:
* @process: A #PolkitUnixProcess.
......@@ -262,7 +312,7 @@ polkit_unix_process_hash (PolkitSubject *subject)
{
PolkitUnixProcess *process = POLKIT_UNIX_PROCESS (subject);
return g_direct_hash (GINT_TO_POINTER ((process->pid + process->start_time))) ;
return g_direct_hash (GSIZE_TO_POINTER ((process->pid + process->start_time))) ;
}
static gboolean
......@@ -387,14 +437,35 @@ get_pid_psinfo (pid_t pid, struct psinfo *ps)
}
#endif
#ifdef HAVE_FREEBSD
static gboolean
get_kinfo_proc (pid_t pid, struct kinfo_proc *p)
{
int mib[4];
size_t len;
len = 4;
sysctlnametomib ("kern.proc.pid", mib, &len);
len = sizeof (struct kinfo_proc);
mib[3] = pid;
if (sysctl (mib, 4, p, &len, NULL, 0) == -1)
return FALSE;
return TRUE;
}
#endif
static guint64
get_start_time_for_pid (pid_t pid,
GError **error)
{
guint64 start_time;
#ifndef HAVE_FREEBSD
gchar *filename;
gchar *contents;
size_t length;
guint64 start_time;
gchar **tokens;
guint num_tokens;
gchar *p;
......@@ -463,6 +534,26 @@ get_start_time_for_pid (pid_t pid,
out:
g_free (filename);
g_free (contents);
#else
struct kinfo_proc p;
start_time = 0;
if (! get_kinfo_proc (pid, &p))
{
g_set_error (error,
POLKIT_ERROR,
POLKIT_ERROR_FAILED,
"Error obtaining start time for %d (%s)",
(gint) pid,
g_strerror (errno));
goto out;
}
start_time = (guint64) p.ki_start.tv_sec;
out:
#endif
return start_time;
}
......@@ -52,6 +52,7 @@ PolkitSubject *polkit_unix_process_new_full (pid_t pid,
guint64 start_time);
pid_t polkit_unix_process_get_pid (PolkitUnixProcess *process);
int polkit_unix_pid_get_uid (pid_t pid, uid_t *uid);
guint64 polkit_unix_process_get_start_time (PolkitUnixProcess *process);
void polkit_unix_process_set_pid (PolkitUnixProcess *process,
......
......@@ -25,6 +25,7 @@
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include "polkitunixuser.h"
#include "polkitidentity.h"
#include "polkiterror.h"
......@@ -210,8 +211,9 @@ polkit_unix_user_new_for_name (const gchar *name,
g_set_error (error,
POLKIT_ERROR,
POLKIT_ERROR_FAILED,
"No UNIX user with name %s: %m",
name);
"No UNIX user with name %s: %s",
name,
g_strerror (errno));
goto out;
}
......
......@@ -35,6 +35,18 @@
# define LOG_AUTHPRIV (10<<3)
#endif
#ifndef HAVE_CLEARENV
extern char **environ;
static int
clearenv (void)
{
if (environ != NULL)
environ[0] = NULL;
return 0;
}
#endif
/* Development aid: define PAH_DEBUG to get debugging output. Do _NOT_
* enable this in production builds; it may leak passwords and other
* sensitive information.
......
......@@ -370,7 +370,7 @@ get_users_in_group (PolkitIdentity *group,
grp = getgrgid (gid);
if (grp == NULL)
{
g_warning ("Error looking up group with gid %d: %m", gid);
g_warning ("Error looking up group with gid %d: %s", gid, g_strerror (errno));
goto out;
}
......@@ -430,7 +430,7 @@ get_groups_for_user (PolkitIdentity *user)
groups,
&num_groups) < 0)
{
g_warning ("Error looking up groups for uid %d: %m", uid);
g_warning ("Error looking up groups for uid %d: %s", uid, g_strerror (errno));
goto out;
}
......
......@@ -382,13 +382,10 @@ polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor
if (POLKIT_IS_UNIX_PROCESS (subject))
{
pid_t pid;
gchar *proc_path;
struct stat statbuf;
pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject));
proc_path = g_strdup_printf ("/proc/%d", pid);
if (g_stat (proc_path, &statbuf) != 0)
if (polkit_unix_pid_get_uid (pid, &uid) != 0)
{
g_set_error (error,
POLKIT_ERROR,
......@@ -397,7 +394,7 @@ polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor
pid);
goto out;
}
user = polkit_unix_user_new (statbuf.st_uid);
user = polkit_unix_user_new (uid);
}
else if (POLKIT_IS_UNIX_SESSION (subject))
{
......
......@@ -35,6 +35,18 @@
#include <polkit/polkit.h>
#ifndef HAVE_CLEARENV
extern char **environ;
static int
clearenv (void)
{
if (environ != NULL)
environ[0] = NULL;
return 0;
}
#endif
static void
usage (int argc, char *argv[])
{
......@@ -188,8 +200,8 @@ main (int argc, char *argv[])
GPtrArray *saved_env;
gchar *opt_user;
pid_t pid_of_caller;
uid_t uid_of_caller;
struct stat statbuf;
gchar procbuf[32];
ret = 127;
authority = NULL;
......@@ -286,7 +298,7 @@ main (int argc, char *argv[])
}
if (stat (path, &statbuf) != 0)
{
g_printerr ("Error getting information about %s: %m\n", path);
g_printerr ("Error getting information about %s: %s\n", path, g_strerror (errno));
goto out;
}
command_line = g_strjoinv (" ", argv + n);
......@@ -312,14 +324,14 @@ main (int argc, char *argv[])
*/
if (clearenv () != 0)
{
g_printerr ("Error clearing environment: %m\n");
g_printerr ("Error clearing environment: %s\n", g_strerror (errno));
goto out;
}
/* Look up information about the user we care about */
if (getpwnam_r (opt_user, &pwstruct, pwbuf, sizeof pwbuf, &pw) != 0)
{
g_printerr ("Error getting information for user %s: %m\n", opt_user);
g_printerr ("Error getting information for user %s: %s\n", opt_user, g_strerror (errno));
goto out;
}
......@@ -340,15 +352,14 @@ main (int argc, char *argv[])
}
/* paranoia: check that the uid of pid_of_caller matches getuid() */
g_snprintf (procbuf, sizeof procbuf, "/proc/%d", pid_of_caller);
if (stat (procbuf, &statbuf) != 0)
if (polkit_unix_pid_get_uid (pid_of_caller, &uid_of_caller) != 0)
{
g_printerr ("Error determing pid of caller (pid %d): %m\n", (gint) pid_of_caller);
g_printerr ("Error determing pid of caller (pid %d): %s\n", (gint) pid_of_caller, g_strerror (errno));
goto out;
}
if (statbuf.st_uid != getuid ())
if (uid_of_caller != getuid ())
{
g_printerr ("User of caller (%d) does not match our uid (%d)\n", statbuf.st_uid, getuid ());
g_printerr ("User of caller (%d) does not match our uid (%d)\n", uid_of_caller, getuid ());
goto out;
}
......@@ -426,9 +437,10 @@ main (int argc, char *argv[])
if (!g_setenv (key, value, TRUE))
{
g_printerr ("Error setting environment variable %s to '%s': %m\n",
g_printerr ("Error setting environment variable %s to '%s': %s\n",
key,
value);
value,
g_strerror (errno));
goto out;
}
}
......@@ -446,7 +458,7 @@ main (int argc, char *argv[])
setreuid (0, 0);
if ((geteuid () != 0) || (getuid () != 0))
{
g_printerr ("Error becoming uid 0: %m\n");
g_printerr ("Error becoming uid 0: %s\n", g_strerror (errno));
goto out;
}
}
......@@ -454,12 +466,12 @@ main (int argc, char *argv[])
/* become the user */
if (setgroups (0, NULL) != 0)
{
g_printerr ("Error setting groups: %m\n");
g_printerr ("Error setting groups: %s\n", g_strerror (errno));
goto out;
}
if (initgroups (pw->pw_name, pw->pw_gid) != 0)
{
g_printerr ("Error initializing groups for %s: %m\n", pw->pw_name);
g_printerr ("Error initializing groups for %s: %s\n", pw->pw_name, g_strerror (errno));
goto out;
}
setregid (pw->pw_gid, pw->pw_gid);
......@@ -467,21 +479,21 @@ main (int argc, char *argv[])
if ((geteuid () != pw->pw_uid) || (getuid () != pw->pw_uid) ||
(getegid () != pw->pw_gid) || (getgid () != pw->pw_gid))
{
g_printerr ("Error becoming real+effective uid %d and gid %d: %m\n", pw->pw_uid, pw->pw_gid);
g_printerr ("Error becoming real+effective uid %d and gid %d: %s\n", pw->pw_uid, pw->pw_gid, g_strerror (errno));
goto out;
}
/* change to home directory */
if (chdir (pw->pw_dir) != 0)
{
g_printerr ("Error changing to home directory %s: %m\n", pw->pw_dir);
g_printerr ("Error changing to home directory %s: %s\n", pw->pw_dir, g_strerror (errno));
goto out;
}
/* exec the program */
if (execv (path, exec_argv) != 0)
{
g_printerr ("Error executing %s: %m\n", path);
g_printerr ("Error executing %s: %s\n", path, g_strerror (errno));
goto out;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment