From patchwork Thu Sep 3 23:33:41 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Zhou X-Patchwork-Id: 514295 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (li376-54.members.linode.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 12F05140771 for ; Fri, 4 Sep 2015 09:34:15 +1000 (AEST) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 470EA10BD7; Thu, 3 Sep 2015 16:34:04 -0700 (PDT) X-Original-To: dev@openvswitch.com Delivered-To: dev@openvswitch.com Received: from mail-pa0-f52.google.com (mail-pa0-f52.google.com [209.85.220.52]) by archives.nicira.com (Postfix) with ESMTPS id 4DF8B10BD6 for ; Thu, 3 Sep 2015 16:34:03 -0700 (PDT) Received: by pacwi10 with SMTP id wi10so4658073pac.3 for ; Thu, 03 Sep 2015 16:33:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=TA5OrW3aOfZd1fNTwfKcIET6+zox4Y0ZdoruhmI/pKI=; b=H6rcWYt0RO4Kcg7s3NnKudu1Zewu7jqgJKNdX93NbIs41r3YjNBu+GPDwqFce4Bv0P /Gcb95g+WRXgMZZvNA6yBd9O0dJF8O10Ja6FW1SK1R3aFIlRo5hiDzRu7Bs/sugz/xBo 5cuxHD/3JcmzWpsg4Z1eSIWqFU/ZvUxIo6cJjbORRYdm5dWNNA+nzibSxxtFsHHpZBas h3RnX9rmsXEn6qPEV16YgYkXX6aiPWbPnvM4fDlvCNwOMBz5ffVQYPg2Mcm3Lxuv5tyz 8zo3fG0NxaShHy3kUgYnaO+oQrpPyoXI/c6h380SXfJXK5JOD7Q8tsiVsrvvJ0ypEbOE /I4A== X-Gm-Message-State: ALoCoQlUh69UN60SeqkwYrfOEZrpWJBbqXavKRSIuuxp7Pb6iA+XGjVqPHVaPKlv6jh84KcUJoPe X-Received: by 10.66.100.234 with SMTP id fb10mr1095728pab.119.1441323237389; Thu, 03 Sep 2015 16:33:57 -0700 (PDT) Received: from ubuntu.localdomain ([208.91.1.34]) by smtp.gmail.com with ESMTPSA id vv2sm247828pab.21.2015.09.03.16.33.56 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 03 Sep 2015 16:33:56 -0700 (PDT) From: Andy Zhou To: dev@openvswitch.com Date: Thu, 3 Sep 2015 16:33:41 -0700 Message-Id: <1441323223-11889-1-git-send-email-azhou@nicira.com> X-Mailer: git-send-email 1.9.1 Subject: [ovs-dev] [PATCH 1/3] lib: add function to switch daemon user at run time X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" Added function to drop daemon's root privileges at run time by allowing it to run as a different user. Daemon can still start running as root. Each daemon's implementation can invoke this function when it is ready to drop the root privilege. Future patch will make use of this function. Signed-off-by: Andy Zhou --- lib/daemon-unix.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- lib/daemon.h | 9 ++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/lib/daemon-unix.c b/lib/daemon-unix.c index eb95521..d52ac2d 100644 --- a/lib/daemon-unix.c +++ b/lib/daemon-unix.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ #include "daemon-private.h" #include #include +#include #include #include #include @@ -64,6 +65,13 @@ static int daemonize_fd = -1; * it dies due to an error signal? */ static bool monitor; +/* --user: Only root can have this option. Switch to new uid:gid after initial + * running as root. */ +static bool switch_to_new_user = false; +static uid_t uid; +static gid_t gid; +static char *user = NULL; + static void check_already_running(void); static int lock_pidfile(FILE *, int command); static pid_t fork_and_clean_up(void); @@ -684,3 +692,43 @@ should_service_stop(void) { return false; } + +void +daemon_become_new_user(void) +{ + if (switch_to_new_user) { + /* "Setuid Demystified" by Hao Chen, etc outlines some caveats of + * around unix system call setuid() and friends. This implementation + * mostly follow the advice given by the paper. The paper is + * published in 2002, so things could have changed. + */ + + /* Change both real and effective uid and gid will permanently + * drop the process' privilege. "Setuid Demystified" suggested + * that calling getuid() after each setuid() call to verify they + * are actually set, because checking return code alone is not + * sufficient. + * + * Linux also has per process file system uid, i.e. fsuid. Without + * explicit setting it, it follows the process' effective uid. + * This implementation does not explicitly set fsuid for better + * portability. (Although setresuid() is not available on Solaris, + * according to the paper above.) */ + + if (setregid(gid, gid) == -1 || getgid() != gid || getegid() != gid) { + VLOG_FATAL("%s: fail to switch group to gid as %d, aborting", + pidfile, gid); + } + + if (user && initgroups(user, gid) == -1) { + VLOG_FATAL("%s: fail to add supplementary group gid %d, aborting", + pidfile, gid); + } + + /* Change both real and effective uid and make sure they are set. */ + if (setreuid(uid, uid) == -1 || getuid() != uid || geteuid() != uid) { + VLOG_FATAL("%s: fail to switch to user %s, aborting", + pidfile, user); + } + } +} diff --git a/lib/daemon.h b/lib/daemon.h index 959341d..fb97cde 100644 --- a/lib/daemon.h +++ b/lib/daemon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -76,6 +76,7 @@ void set_detach(void); void daemon_set_monitor(void); void set_no_chdir(void); void ignore_existing_pidfile(void); +void daemon_become_new_user(void); pid_t read_pidfile(const char *name); #else #define DAEMON_OPTION_ENUMS \ @@ -117,6 +118,12 @@ pid_t read_pidfile(const char *name); void control_handler(DWORD request); void set_pipe_handle(const char *pipe_handle); + +static inline void +daemon_become_new_user(void) +{ + /* Not implemented. */ +} #endif /* _WIN32 */ bool get_detach(void);