diff options
Diffstat (limited to 'usr/src/cmd/cmd-inet/lib')
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile | 4 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c | 37 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h | 25 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c | 76 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_path.c | 84 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c | 38 |
6 files changed, 200 insertions, 64 deletions
diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile b/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile index 1c32ce2ff1..1ec235b9a5 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile @@ -21,6 +21,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2015 Joyent, Inc. # Copyright 2021 Tintri by DDN, Inc. All rights reserved. # @@ -28,7 +29,8 @@ include ../../../../lib/Makefile.lib PROG= ipmgmtd -OBJS= ipmgmt_main.o ipmgmt_door.o ipmgmt_persist.o ipmgmt_util.o +OBJS= ipmgmt_main.o ipmgmt_door.o ipmgmt_persist.o ipmgmt_util.o \ + ipmgmt_path.o SRCS= $(OBJS:.o=.c) SVCMETHOD= net-ipmgmt MANIFEST= network-ipmgmt.xml diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c index e3f18fea71..45080518b4 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2014, Joyent, Inc. All rights reserved. * Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>. * Copyright 2021, Tintri by DDN. All rights reserved. * Copyright 2022, Oxide Computer Company. @@ -120,7 +121,9 @@ ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp, goto fail; } - /* check for solaris.network.interface.config authorization */ + /* + * if not root, check for solaris.network.interface.config authorization + */ if (infop->idi_set) { uid_t uid; struct passwd pwd; @@ -132,24 +135,32 @@ ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp, goto fail; } uid = ucred_getruid(cred); + ucred_free(cred); if ((int)uid < 0) { err = errno; ipmgmt_log(LOG_ERR, "Could not get user id."); goto fail; } - if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) == - NULL) { - err = errno; - ipmgmt_log(LOG_ERR, "Could not get password entry."); - goto fail; - } - if (chkauthattr(NETWORK_INTERFACE_CONFIG_AUTH, - pwd.pw_name) != 1) { - err = EPERM; - ipmgmt_log(LOG_ERR, "Not authorized for operation."); - goto fail; + + /* + * Branded zones may have different auth, but root always + * allowed. + */ + if (uid != 0) { + if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) == NULL) { + err = errno; + ipmgmt_log(LOG_ERR, + "Could not get password entry."); + goto fail; + } + if (chkauthattr(NETWORK_INTERFACE_CONFIG_AUTH, + pwd.pw_name) != 1) { + err = EPERM; + ipmgmt_log(LOG_ERR, + "Not authorized for operation."); + goto fail; + } } - ucred_free(cred); } /* individual handlers take care of calling door_return */ diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h index fe7e95a87e..bf70839f36 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015 Joyent, Inc. * Copyright (c) 2016, Chris Fraire <cfraire@me.com>. * Copyright 2021 Tintri by DDN, Inc. All rights reserved. */ @@ -144,8 +145,6 @@ extern ipmgmt_aobjmap_list_t aobjmap; #define ADDROBJ_LOOKUPADD 0x00000004 #define ADDROBJ_SETLIFNUM 0x00000008 -/* Permanent data store for ipadm */ -#define IPADM_DB_FILE "/etc/ipadm/ipadm.conf" #define IPADM_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) /* @@ -155,20 +154,12 @@ extern ipmgmt_aobjmap_list_t aobjmap; */ #define IPADM_DB_VERSION 1 -/* - * A temporary file created in SMF volatile filesystem. This file captures the - * in-memory copy of list `aobjmap' on disk. This is done to recover from - * daemon reboot (using svcadm) or crashes. - */ -#define IPADM_TMPFS_DIR "/etc/svc/volatile/ipadm" -#define ADDROBJ_MAPPING_DB_FILE IPADM_TMPFS_DIR"/aobjmap.conf" - -/* - * A temporary copy of the ipadm configuration file might need - * to be created if write requests are encountered during boottime - * and the root filesystem is mounted read-only. - */ -#define IPADM_VOL_DB_FILE IPADM_TMPFS_DIR"/ipadm.conf" +typedef enum ipadm_path { + IPADM_PATH_TMPFS_DIR = 1, + IPADM_PATH_ADDROBJ_MAP_DB, + IPADM_PATH_DB, + IPADM_PATH_VOL_DB +} ipadm_path_t; /* SCF resources required to interact with svc.configd */ typedef struct scf_resources { @@ -200,6 +191,8 @@ extern void ipmgmt_release_scf_resources(scf_resources_t *); extern boolean_t ipmgmt_needs_upgrade(scf_resources_t *); extern void ipmgmt_update_dbver(scf_resources_t *); +extern void ipmgmt_path(ipadm_path_t, char *, size_t); + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c index c31c91a547..41aeb2d98c 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015 Joyent, Inc. * Copyright 2021 Tintri by DDN, Inc. All rights reserved. */ @@ -106,6 +107,7 @@ ipmgmt_db_init() int fd, err, scferr; scf_resources_t res; boolean_t upgrade = B_TRUE; + char aobjpath[MAXPATHLEN]; /* * Check to see if we need to upgrade the data-store. We need to @@ -135,11 +137,11 @@ ipmgmt_db_init() ipmgmt_release_scf_resources(&res); /* creates the address object data store, if it doesn't exist */ - if ((fd = open(ADDROBJ_MAPPING_DB_FILE, O_CREAT|O_RDONLY, - IPADM_FILE_MODE)) == -1) { + ipmgmt_path(IPADM_PATH_ADDROBJ_MAP_DB, aobjpath, sizeof (aobjpath)); + if ((fd = open(aobjpath, O_CREAT|O_RDONLY, IPADM_FILE_MODE)) == -1) { err = errno; - ipmgmt_log(LOG_ERR, "could not open %s: %s", - ADDROBJ_MAPPING_DB_FILE, strerror(err)); + ipmgmt_log(LOG_ERR, "could not open %s: %s", aobjpath, + strerror(err)); return (err); } (void) close(fd); @@ -153,8 +155,8 @@ ipmgmt_db_init() * representation of the mapping. That is, build `aobjmap' structure * from address object data store. */ - if ((err = ipadm_rw_db(ipmgmt_aobjmap_init, NULL, - ADDROBJ_MAPPING_DB_FILE, 0, IPADM_DB_READ)) != 0) { + if ((err = ipadm_rw_db(ipmgmt_aobjmap_init, NULL, aobjpath, 0, + IPADM_DB_READ)) != 0) { /* if there was nothing to initialize, it's fine */ if (err != ENOENT) return (err); @@ -166,17 +168,42 @@ ipmgmt_db_init() return (err); } +static const char * +ipmgmt_door_path() +{ + static char door[MAXPATHLEN]; + static boolean_t init_done = B_FALSE; + + if (!init_done) { + const char *zroot = zone_get_nroot(); + + /* + * If this is a branded zone, make sure we use the "/native" + * prefix for the door path: + */ + (void) snprintf(door, sizeof (door), "%s%s", zroot != NULL ? + zroot : "", IPMGMT_DOOR); + + init_done = B_TRUE; + } + + return (door); +} + static int ipmgmt_door_init() { int fd; int err; + const char *door = ipmgmt_door_path(); - /* create the door file for ipmgmtd */ - if ((fd = open(IPMGMT_DOOR, O_CREAT|O_RDONLY, IPADM_FILE_MODE)) == -1) { + /* + * Create the door file for ipmgmtd. + */ + if ((fd = open(door, O_CREAT | O_RDONLY, IPADM_FILE_MODE)) == -1) { err = errno; - ipmgmt_log(LOG_ERR, "could not open %s: %s", - IPMGMT_DOOR, strerror(err)); + ipmgmt_log(LOG_ERR, "could not open %s: %s", door, + strerror(err)); return (err); } (void) close(fd); @@ -187,15 +214,16 @@ ipmgmt_door_init() ipmgmt_log(LOG_ERR, "failed to create door: %s", strerror(err)); return (err); } + /* * fdetach first in case a previous daemon instance exited * ungracefully. */ - (void) fdetach(IPMGMT_DOOR); - if (fattach(ipmgmt_door_fd, IPMGMT_DOOR) != 0) { + (void) fdetach(door); + if (fattach(ipmgmt_door_fd, door) != 0) { err = errno; - ipmgmt_log(LOG_ERR, "failed to attach door to %s: %s", - IPMGMT_DOOR, strerror(err)); + ipmgmt_log(LOG_ERR, "failed to attach door to %s: %s", door, + strerror(err)); goto fail; } return (0); @@ -208,13 +236,15 @@ fail: static void ipmgmt_door_fini() { + const char *door = ipmgmt_door_path(); + if (ipmgmt_door_fd == -1) return; - (void) fdetach(IPMGMT_DOOR); + (void) fdetach(door); if (door_revoke(ipmgmt_door_fd) == -1) { ipmgmt_log(LOG_ERR, "failed to revoke access to door %s: %s", - IPMGMT_DOOR, strerror(errno)); + door, strerror(errno)); } } @@ -351,10 +381,14 @@ ipmgmt_init_privileges() { struct stat statbuf; int err; + char tmpfsdir[MAXPATHLEN]; - /* create the IPADM_TMPFS_DIR directory */ - if (stat(IPADM_TMPFS_DIR, &statbuf) < 0) { - if (mkdir(IPADM_TMPFS_DIR, (mode_t)0755) < 0) { + /* + * Create the volatile storage directory: + */ + ipmgmt_path(IPADM_PATH_TMPFS_DIR, tmpfsdir, sizeof (tmpfsdir)); + if (stat(tmpfsdir, &statbuf) < 0) { + if (mkdir(tmpfsdir, (mode_t)0755) < 0) { err = errno; goto fail; } @@ -365,8 +399,8 @@ ipmgmt_init_privileges() } } - if ((chmod(IPADM_TMPFS_DIR, 0755) < 0) || - (chown(IPADM_TMPFS_DIR, UID_NETADM, GID_NETADM) < 0)) { + if ((chmod(tmpfsdir, 0755) < 0) || + (chown(tmpfsdir, UID_NETADM, GID_NETADM) < 0)) { err = errno; goto fail; } diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_path.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_path.c new file mode 100644 index 0000000000..0219ac1522 --- /dev/null +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_path.c @@ -0,0 +1,84 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +/* + * Lookup functions for various file paths used by ipmgmtd. This mechanism + * primarily exists to account for a native root prefix when run within a + * branded zone (e.g. "/native"). + */ + +#include <stdio.h> +#include <zone.h> +#include "ipmgmt_impl.h" + +#define IPADM_PERM_DIR "/etc/ipadm" +#define IPADM_TMPFS_DIR "/etc/svc/volatile/ipadm" + +typedef struct ipadm_path_ent { + ipadm_path_t ipe_id; + const char *ipe_path; +} ipadm_path_ent_t; + +static ipadm_path_ent_t ipadm_paths[] = { + /* + * A temporary directory created in the SMF volatile filesystem. + */ + { IPADM_PATH_TMPFS_DIR, IPADM_TMPFS_DIR }, + + /* + * This file captures the in-memory copy of list `aobjmap' on disk. + * This allows the system to recover in the event that the daemon + * crashes or is restarted. + */ + { IPADM_PATH_ADDROBJ_MAP_DB, IPADM_TMPFS_DIR "/aobjmap.conf" }, + + /* + * The permanent data store for ipadm. + */ + { IPADM_PATH_DB, IPADM_PERM_DIR "/ipadm.conf" }, + + /* + * A temporary copy of the ipadm configuration created, if needed, to + * service write requests early in boot. This file is merged with the + * permanent data store once it is available for writes. + */ + { IPADM_PATH_VOL_DB, IPADM_TMPFS_DIR "/ipadm.conf" }, + + { 0, NULL } +}; + +/* + * Load one of the paths used by ipadm into the provided string buffer. + * Prepends the native system prefix (e.g. "/native") if one is in effect, + * such as when running within a branded zone. + */ +void +ipmgmt_path(ipadm_path_t ip, char *buf, size_t bufsz) +{ + int i; + + for (i = 0; ipadm_paths[i].ipe_path != NULL; i++) { + if (ipadm_paths[i].ipe_id == ip) { + const char *zroot = zone_get_nroot(); + + (void) snprintf(buf, bufsz, "%s%s", zroot != NULL ? + zroot : "", ipadm_paths[i].ipe_path); + + return; + } + } + + abort(); +} diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c index e29ecbaeb2..0c44b51f5a 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c @@ -542,13 +542,18 @@ static void * ipmgmt_db_restore_thread(void *arg) { int err; + char confpath[MAXPATHLEN]; + char tmpconfpath[MAXPATHLEN]; + + ipmgmt_path(IPADM_PATH_DB, confpath, sizeof (confpath)); + ipmgmt_path(IPADM_PATH_VOL_DB, tmpconfpath, sizeof (tmpconfpath)); for (;;) { (void) sleep(5); (void) pthread_rwlock_wrlock(&ipmgmt_dbconf_lock); if (!ipmgmt_rdonly_root) break; - err = ipmgmt_cpfile(IPADM_VOL_DB_FILE, IPADM_DB_FILE, B_FALSE); + err = ipmgmt_cpfile(tmpconfpath, confpath, B_FALSE); if (err == 0) { ipmgmt_rdonly_root = B_FALSE; break; @@ -580,6 +585,11 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) mode_t mode; pthread_t tid; pthread_attr_t attr; + char confpath[MAXPATHLEN]; + char tmpconfpath[MAXPATHLEN]; + + ipmgmt_path(IPADM_PATH_DB, confpath, sizeof (confpath)); + ipmgmt_path(IPADM_PATH_VOL_DB, tmpconfpath, sizeof (tmpconfpath)); writeop = (db_op != IPADM_DB_READ); if (writeop) { @@ -592,11 +602,10 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) /* * Did a previous write attempt fail? If so, don't even try to - * read/write to IPADM_DB_FILE. + * read/write to the permanent configuration file. */ if (!ipmgmt_rdonly_root) { - err = ipadm_rw_db(db_walk_func, db_warg, IPADM_DB_FILE, - mode, db_op); + err = ipadm_rw_db(db_walk_func, db_warg, confpath, mode, db_op); if (err != EROFS) goto done; } @@ -604,11 +613,11 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) /* * If we haven't already copied the file to the volatile * file system, do so. This should only happen on a failed - * writeop(i.e., we have acquired the write lock above). + * writeop (i.e., we have acquired the write lock above). */ - if (access(IPADM_VOL_DB_FILE, F_OK) != 0) { + if (access(tmpconfpath, F_OK) != 0) { assert(writeop); - err = ipmgmt_cpfile(IPADM_DB_FILE, IPADM_VOL_DB_FILE, B_TRUE); + err = ipmgmt_cpfile(confpath, tmpconfpath, B_TRUE); if (err != 0) goto done; (void) pthread_attr_init(&attr); @@ -619,7 +628,7 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) NULL); (void) pthread_attr_destroy(&attr); if (err != 0) { - (void) unlink(IPADM_VOL_DB_FILE); + (void) unlink(tmpconfpath); goto done; } ipmgmt_rdonly_root = B_TRUE; @@ -628,7 +637,7 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) /* * Read/write from the volatile copy. */ - err = ipadm_rw_db(db_walk_func, db_warg, IPADM_VOL_DB_FILE, + err = ipadm_rw_db(db_walk_func, db_warg, tmpconfpath, mode, db_op); done: (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock); @@ -1506,6 +1515,9 @@ ipmgmt_persist_aobjmap(ipmgmt_aobjmap_t *nodep, ipadm_db_op_t op) int err; ipadm_dbwrite_cbarg_t cb; nvlist_t *nvl = NULL; + char aobjpath[MAXPATHLEN]; + + ipmgmt_path(IPADM_PATH_ADDROBJ_MAP_DB, aobjpath, sizeof (aobjpath)); if (op == IPADM_DB_WRITE) { if ((err = i_ipmgmt_node2nvl(&nvl, nodep)) != 0) @@ -1516,14 +1528,14 @@ ipmgmt_persist_aobjmap(ipmgmt_aobjmap_t *nodep, ipadm_db_op_t op) else cb.dbw_flags = 0; - err = ipadm_rw_db(ipmgmt_update_aobjmap, &cb, - ADDROBJ_MAPPING_DB_FILE, IPADM_FILE_MODE, IPADM_DB_WRITE); + err = ipadm_rw_db(ipmgmt_update_aobjmap, &cb, aobjpath, + IPADM_FILE_MODE, IPADM_DB_WRITE); nvlist_free(nvl); } else { assert(op == IPADM_DB_DELETE); - err = ipadm_rw_db(ipmgmt_delete_aobjmap, nodep, - ADDROBJ_MAPPING_DB_FILE, IPADM_FILE_MODE, IPADM_DB_DELETE); + err = ipadm_rw_db(ipmgmt_delete_aobjmap, nodep, aobjpath, + IPADM_FILE_MODE, IPADM_DB_DELETE); } return (err); } |