[ovs-dev] [PATCH 2/3] service controller: Allow change to punix socket file group ownership.
Alex Wang
alexw at nicira.com
Sat Aug 22 06:10:32 UTC 2015
This commit adds a new key-value pair, 'punix_file_group=<user group>',
to the 'other_config' column in the 'Controller' table. This new config
allows user to change the punix socket file's group ownership, so that
non-root process can also connect to ovs bridge.
Signed-off-by: Alex Wang <alexw at nicira.com>
---
lib/socket-util-unix.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/socket-util.h | 7 +++++
vswitchd/bridge.c | 17 ++++++++++++
vswitchd/vswitch.xml | 16 +++++++++++
4 files changed, 110 insertions(+)
diff --git a/lib/socket-util-unix.c b/lib/socket-util-unix.c
index afab195..40105cb 100644
--- a/lib/socket-util-unix.c
+++ b/lib/socket-util-unix.c
@@ -19,6 +19,7 @@
#include <errno.h>
#include <fcntl.h>
#include <net/if.h>
+#include <grp.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -49,6 +50,75 @@ VLOG_DEFINE_THIS_MODULE(socket_util_unix);
* space for a null terminator. */
#define MAX_UN_LEN (sizeof(((struct sockaddr_un *) 0)->sun_path) - 1)
+/* Given 'group_name', returns true if the corresponding 'group'
+ * is found and saves the group id into 'gid'. Returns false if
+ * cannot find 'group'. */
+static bool
+query_group_gid(const char *group_name, gid_t *gid)
+{
+ struct group group;
+ struct group *result;
+ size_t buflen;
+ char *buf;
+
+ if (!group_name) {
+ return false;
+ }
+
+ buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
+ buf = xmalloc(buflen * sizeof *buf);
+ getgrnam_r(group_name, &group, buf, buflen, &result);
+
+ if (!result) {
+ VLOG_ERR("cannot retrieve group info for specified group "
+ "(%s) : %s",
+ group_name,
+ errno ? ovs_strerror(errno) : "group not found");
+ } else {
+ *gid = result->gr_gid;
+ }
+ free(buf);
+
+ return result;
+}
+
+/* Sets the unix domain socket file's group ownership to 'group'. */
+void
+unix_socket_set_file_group(const char *path, const char *group)
+{
+ struct stat info;
+ gid_t gid = 0;
+
+ if (stat(path, &info)) {
+ VLOG_WARN("set (%s) group fails : cannot find file (%s)",
+ path, path);
+ return;
+ }
+
+ if (!query_group_gid(group ? group : "root", &gid)) {
+ VLOG_WARN("set (%s) group fails : cannot find group (%s)",
+ path, group ? group : "root");
+ return;
+ }
+
+ /* Returns if current group id is same as desired group id. */
+ if (gid == info.st_gid) {
+ return;
+ } else {
+ /* Changes group ownership to 'gid'. */
+ if (chown(path, -1, gid)) {
+ VLOG_WARN("chown (%s) group to (%s) fails: %s",
+ path, group ? group : "root", ovs_strerror(errno));
+ return;
+ }
+ if (chmod(path, 0770)) {
+ VLOG_WARN("chmod (%s) permission to 0700 fails: %s",
+ path, ovs_strerror(errno));
+ return;
+ }
+ }
+}
+
void
xpipe(int fds[2])
{
diff --git a/lib/socket-util.h b/lib/socket-util.h
index 8015c7f..77c251c 100644
--- a/lib/socket-util.h
+++ b/lib/socket-util.h
@@ -81,6 +81,7 @@ void xpipe_nonblocking(int fds[2]);
int drain_rcvbuf(int fd);
+void unix_socket_set_file_group(const char *path, const char *group);
int make_unix_socket(int style, bool nonblock,
const char *bind_path, const char *connect_path);
int get_unix_name_len(socklen_t sun_len);
@@ -95,6 +96,12 @@ int af_inet_ifreq_ioctl(const char *name, struct ifreq *,
#endif
#ifdef _WIN32
+static inline void unix_socket_set_file_group(const char *path,
+ const char *group)
+{
+ return;
+}
+
static inline int make_unix_socket(int style, bool nonblock,
const char *bind_path,
const char *connect_path)
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index b95610d..c931247 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -3507,6 +3507,7 @@ bridge_configure_remotes(struct bridge *br,
enum ofproto_fail_mode fail_mode;
+ const char **punix_file_groups;
struct ofproto_controller *ocs;
size_t n_ocs;
size_t i;
@@ -3528,9 +3529,12 @@ bridge_configure_remotes(struct bridge *br,
n_controllers = bridge_get_controllers(br, &controllers);
+ punix_file_groups =
+ xmalloc((n_controllers + 1) * sizeof *punix_file_groups);
ocs = xmalloc((n_controllers + 1) * sizeof *ocs);
n_ocs = 0;
+ punix_file_groups[n_ocs] = NULL;
bridge_ofproto_controller_for_mgmt(br, &ocs[n_ocs++]);
for (i = 0; i < n_controllers; i++) {
struct ovsrec_controller *c = controllers[i];
@@ -3584,6 +3588,8 @@ bridge_configure_remotes(struct bridge *br,
bridge_configure_local_iface_netdev(br, c);
bridge_ofproto_controller_from_ovsrec(c, &ocs[n_ocs]);
+ punix_file_groups[n_ocs] = smap_get(&c->other_config,
+ "punix_file_group");
if (disable_in_band) {
ocs[n_ocs].band = OFPROTO_OUT_OF_BAND;
}
@@ -3592,6 +3598,17 @@ bridge_configure_remotes(struct bridge *br,
ofproto_set_controllers(br->ofproto, ocs, n_ocs,
bridge_get_allowed_versions(br));
+
+ for (i = 0; i < n_ocs; i++) {
+ if (!strncmp(ocs[i].target, "punix:", 6)) {
+ const char *path = ocs[i].target + 6;
+ const char *group = punix_file_groups[i];
+
+ unix_socket_set_file_group(path, group);
+ }
+ }
+
+ free(punix_file_groups);
free(ocs[0].target); /* From bridge_ofproto_controller_for_mgmt(). */
free(ocs);
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 457f34a..6f6e0ed 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -3989,6 +3989,22 @@
a default value of 48 is chosen. Valid DSCP values must be in the
range 0 to 63.
</column>
+
+ <column name="other_config" key="punix_file_group"
+ type='{"type": "string"}'>
+ <p>
+ When connection method in <ref column="target"/> is
+ <code>punix</code>, this config specifies the user group to which
+ the group ownership for 'punix' (unix domain socket) file created
+ by ovs will be applied. Also, the file's access permission will be
+ changed to '0770'.
+ </p>
+ <p>
+ By default, the 'punix' file is associated with the 'root'
+ group and have access permission '0700'. If this config is
+ not specified or specified as 'root', the default is restored.
+ </p>
+ </column>
</group>
--
1.7.9.5
More information about the dev
mailing list