summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2020-06-22 11:36:27 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2020-06-22 11:36:27 +0000
commit542213b19f73f84fe38a0c734394135d8a4041d8 (patch)
tree2ac84f50820b7d6bbf7016c88517ae401e18fb5f /usr
parent001cfa178a95def0f13cf06ea25b89bf4acc6651 (diff)
parentc686756220120076a07be0dcce54be698101a3d1 (diff)
downloadillumos-joyent-542213b19f73f84fe38a0c734394135d8a4041d8.tar.gz
[illumos-gate merge]
commit c686756220120076a07be0dcce54be698101a3d1 12541 sgs: smatch and NULL pointer errors commit d865fc92e4b640c73c2957a20b3d82622c741be5 12824 recvmsg(): adjust final cmsg->cmsg_len upon MSG_CTRUNC commit ce5f7fb896fce369b4ec50da6d3a232bce2458ce 12836 loader: strings in nvlist are counted strings, not c-strings
Diffstat (limited to 'usr')
-rw-r--r--usr/src/boot/Makefile.version2
-rw-r--r--usr/src/boot/lib/libstand/zfs/zfsimpl.c171
-rw-r--r--usr/src/cmd/sgs/error/common/errorinput.c30
-rw-r--r--usr/src/cmd/sgs/error/common/errorsubr.c25
-rw-r--r--usr/src/cmd/sgs/error/common/errortouch.c58
-rw-r--r--usr/src/cmd/sgs/rtld/common/a.out.c4
-rw-r--r--usr/src/cmd/sgs/rtld/common/cache_a.out.c79
-rw-r--r--usr/src/pkg/manifests/system-test-ostest.mf3
-rw-r--r--usr/src/test/os-tests/runfiles/default.run4
-rw-r--r--usr/src/test/os-tests/tests/sockfs/Makefile24
-rw-r--r--usr/src/test/os-tests/tests/sockfs/rights.c700
-rw-r--r--usr/src/uts/common/fs/sockfs/socksubr.c43
-rw-r--r--usr/src/uts/common/fs/sockfs/socksyscalls.c62
-rw-r--r--usr/src/uts/common/sys/socketvar.h4
14 files changed, 1010 insertions, 199 deletions
diff --git a/usr/src/boot/Makefile.version b/usr/src/boot/Makefile.version
index 7b173d0d47..f48764b495 100644
--- a/usr/src/boot/Makefile.version
+++ b/usr/src/boot/Makefile.version
@@ -33,4 +33,4 @@ LOADER_VERSION = 1.1
# Use date like formatting here, YYYY.MM.DD.XX, without leading zeroes.
# The version is processed from left to right, the version number can only
# be increased.
-BOOT_VERSION = $(LOADER_VERSION)-2020.05.09.1
+BOOT_VERSION = $(LOADER_VERSION)-2020.06.10.1
diff --git a/usr/src/boot/lib/libstand/zfs/zfsimpl.c b/usr/src/boot/lib/libstand/zfs/zfsimpl.c
index a5c0d4fc73..ce3180d493 100644
--- a/usr/src/boot/lib/libstand/zfs/zfsimpl.c
+++ b/usr/src/boot/lib/libstand/zfs/zfsimpl.c
@@ -193,7 +193,7 @@ xdr_uint64_t(const unsigned char **xdr, uint64_t *lp)
static int
nvlist_find(const unsigned char *nvlist, const char *name, int type,
- int *elementsp, void *valuep)
+ int *elementsp, void *valuep, int *sizep)
{
const unsigned char *p, *pair;
int junk;
@@ -225,6 +225,8 @@ nvlist_find(const unsigned char *nvlist, const char *name, int type,
} else if (type == DATA_TYPE_STRING) {
int len;
xdr_int(&p, &len);
+ if (sizep != NULL)
+ *sizep = len;
(*(const char **)valuep) = (const char *)p;
return (0);
} else if (type == DATA_TYPE_NVLIST ||
@@ -389,7 +391,7 @@ nvlist_print(const unsigned char *nvlist, unsigned int indent)
for (i = 0; i < indent; i++)
printf(" ");
- printf("%s %s", typenames[pairtype], pairname);
+ printf("%s %.*s", typenames[pairtype], namelen, pairname);
xdr_int(&p, &elements);
switch (pairtype) {
@@ -403,7 +405,7 @@ nvlist_print(const unsigned char *nvlist, unsigned int indent)
case DATA_TYPE_STRING: {
int len;
xdr_int(&p, &len);
- printf(" = \"%s\"\n", p);
+ printf(" = \"%.*s\"\n", len, p);
break;
}
@@ -419,8 +421,8 @@ nvlist_print(const unsigned char *nvlist, unsigned int indent)
if (j != elements - 1) {
for (i = 0; i < indent; i++)
printf(" ");
- printf("%s %s", typenames[pairtype],
- pairname);
+ printf("%s %.*s", typenames[pairtype],
+ namelen, pairname);
}
}
break;
@@ -1083,17 +1085,17 @@ vdev_set_initial_state(vdev_t *vdev, const unsigned char *nvlist)
is_offline = is_removed = is_faulted = is_degraded = isnt_present = 0;
is_log = 0;
(void) nvlist_find(nvlist, ZPOOL_CONFIG_OFFLINE, DATA_TYPE_UINT64, NULL,
- &is_offline);
+ &is_offline, NULL);
(void) nvlist_find(nvlist, ZPOOL_CONFIG_REMOVED, DATA_TYPE_UINT64, NULL,
- &is_removed);
+ &is_removed, NULL);
(void) nvlist_find(nvlist, ZPOOL_CONFIG_FAULTED, DATA_TYPE_UINT64, NULL,
- &is_faulted);
+ &is_faulted, NULL);
(void) nvlist_find(nvlist, ZPOOL_CONFIG_DEGRADED, DATA_TYPE_UINT64,
- NULL, &is_degraded);
+ NULL, &is_degraded, NULL);
(void) nvlist_find(nvlist, ZPOOL_CONFIG_NOT_PRESENT, DATA_TYPE_UINT64,
- NULL, &isnt_present);
+ NULL, &isnt_present, NULL);
(void) nvlist_find(nvlist, ZPOOL_CONFIG_IS_LOG, DATA_TYPE_UINT64, NULL,
- &is_log);
+ &is_log, NULL);
if (is_offline != 0)
vdev->v_state = VDEV_STATE_OFFLINE;
@@ -1115,34 +1117,37 @@ vdev_init(uint64_t guid, const unsigned char *nvlist, vdev_t **vdevp)
uint64_t id, ashift, asize, nparity;
const char *path;
const char *type;
+ int len, pathlen;
+ char *name;
vdev_t *vdev;
- if (nvlist_find(nvlist, ZPOOL_CONFIG_ID, DATA_TYPE_UINT64, NULL, &id) ||
+ if (nvlist_find(nvlist, ZPOOL_CONFIG_ID, DATA_TYPE_UINT64, NULL, &id,
+ NULL) ||
nvlist_find(nvlist, ZPOOL_CONFIG_TYPE, DATA_TYPE_STRING,
- NULL, &type)) {
+ NULL, &type, &len)) {
return (ENOENT);
}
- if (strcmp(type, VDEV_TYPE_MIRROR) != 0 &&
- strcmp(type, VDEV_TYPE_DISK) != 0 &&
+ if (memcmp(type, VDEV_TYPE_MIRROR, len) != 0 &&
+ memcmp(type, VDEV_TYPE_DISK, len) != 0 &&
#ifdef ZFS_TEST
- strcmp(type, VDEV_TYPE_FILE) != 0 &&
+ memcmp(type, VDEV_TYPE_FILE, len) != 0 &&
#endif
- strcmp(type, VDEV_TYPE_RAIDZ) != 0 &&
- strcmp(type, VDEV_TYPE_INDIRECT) != 0 &&
- strcmp(type, VDEV_TYPE_REPLACING) != 0) {
+ memcmp(type, VDEV_TYPE_RAIDZ, len) != 0 &&
+ memcmp(type, VDEV_TYPE_INDIRECT, len) != 0 &&
+ memcmp(type, VDEV_TYPE_REPLACING, len) != 0) {
printf("ZFS: can only boot from disk, mirror, raidz1, "
"raidz2 and raidz3 vdevs\n");
return (EIO);
}
- if (strcmp(type, VDEV_TYPE_MIRROR) == 0)
+ if (memcmp(type, VDEV_TYPE_MIRROR, len) == 0)
vdev = vdev_create(guid, vdev_mirror_read);
- else if (strcmp(type, VDEV_TYPE_RAIDZ) == 0)
+ else if (memcmp(type, VDEV_TYPE_RAIDZ, len) == 0)
vdev = vdev_create(guid, vdev_raidz_read);
- else if (strcmp(type, VDEV_TYPE_REPLACING) == 0)
+ else if (memcmp(type, VDEV_TYPE_REPLACING, len) == 0)
vdev = vdev_create(guid, vdev_replacing_read);
- else if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) {
+ else if (memcmp(type, VDEV_TYPE_INDIRECT, len) == 0) {
vdev_indirect_config_t *vic;
vdev = vdev_create(guid, vdev_indirect_read);
@@ -1153,15 +1158,15 @@ vdev_init(uint64_t guid, const unsigned char *nvlist, vdev_t **vdevp)
nvlist_find(nvlist,
ZPOOL_CONFIG_INDIRECT_OBJECT,
DATA_TYPE_UINT64,
- NULL, &vic->vic_mapping_object);
+ NULL, &vic->vic_mapping_object, NULL);
nvlist_find(nvlist,
ZPOOL_CONFIG_INDIRECT_BIRTHS,
DATA_TYPE_UINT64,
- NULL, &vic->vic_births_object);
+ NULL, &vic->vic_births_object, NULL);
nvlist_find(nvlist,
ZPOOL_CONFIG_PREV_INDIRECT_VDEV,
DATA_TYPE_UINT64,
- NULL, &vic->vic_prev_indirect_vdev);
+ NULL, &vic->vic_prev_indirect_vdev, NULL);
}
} else {
vdev = vdev_create(guid, vdev_disk_read);
@@ -1173,51 +1178,67 @@ vdev_init(uint64_t guid, const unsigned char *nvlist, vdev_t **vdevp)
vdev_set_initial_state(vdev, nvlist);
vdev->v_id = id;
if (nvlist_find(nvlist, ZPOOL_CONFIG_ASHIFT,
- DATA_TYPE_UINT64, NULL, &ashift) == 0)
+ DATA_TYPE_UINT64, NULL, &ashift, NULL) == 0)
vdev->v_ashift = ashift;
if (nvlist_find(nvlist, ZPOOL_CONFIG_ASIZE,
- DATA_TYPE_UINT64, NULL, &asize) == 0) {
+ DATA_TYPE_UINT64, NULL, &asize, NULL) == 0) {
vdev->v_psize = asize +
VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE;
}
if (nvlist_find(nvlist, ZPOOL_CONFIG_NPARITY,
- DATA_TYPE_UINT64, NULL, &nparity) == 0)
+ DATA_TYPE_UINT64, NULL, &nparity, NULL) == 0)
vdev->v_nparity = nparity;
if (nvlist_find(nvlist, ZPOOL_CONFIG_PATH,
- DATA_TYPE_STRING, NULL, &path) == 0) {
- if (strncmp(path, "/dev/dsk/", 9) == 0)
- path += 9;
- vdev->v_name = strdup(path);
+ DATA_TYPE_STRING, NULL, &path, &pathlen) == 0) {
+ char prefix[] = "/dev/dsk/";
+
+ len = strlen(prefix);
+ if (len < pathlen && memcmp(path, prefix, len) == 0) {
+ path += len;
+ pathlen -= len;
+ }
+ name = malloc(pathlen + 1);
+ if (name != NULL) {
+ bcopy(path, name, pathlen);
+ name[pathlen] = '\0';
+ }
+ vdev->v_name = name;
+ vdev->v_phys_path = NULL;
+ vdev->v_devid = NULL;
if (nvlist_find(nvlist, ZPOOL_CONFIG_PHYS_PATH,
- DATA_TYPE_STRING, NULL, &path) == 0) {
- vdev->v_phys_path = strdup(path);
- } else {
- vdev->v_phys_path = NULL;
+ DATA_TYPE_STRING, NULL, &path, &pathlen) == 0) {
+ name = malloc(pathlen + 1);
+ if (name != NULL) {
+ bcopy(path, name, pathlen);
+ name[pathlen] = '\0';
+ vdev->v_phys_path = name;
+ }
}
if (nvlist_find(nvlist, ZPOOL_CONFIG_DEVID,
- DATA_TYPE_STRING, NULL, &path) == 0) {
- vdev->v_devid = strdup(path);
- } else {
- vdev->v_devid = NULL;
+ DATA_TYPE_STRING, NULL, &path, &pathlen) == 0) {
+ name = malloc(pathlen + 1);
+ if (name != NULL) {
+ bcopy(path, name, pathlen);
+ name[pathlen] = '\0';
+ vdev->v_devid = name;
+ }
}
} else {
- char *name;
-
name = NULL;
- if (strcmp(type, "raidz") == 0) {
+ if (memcmp(type, VDEV_TYPE_RAIDZ, len) == 0) {
if (vdev->v_nparity < 1 ||
vdev->v_nparity > 3) {
printf("ZFS: invalid raidz parity: %d\n",
vdev->v_nparity);
return (EIO);
}
- (void) asprintf(&name, "%s%d-%" PRIu64, type,
+ (void) asprintf(&name, "%.*s%d-%" PRIu64, len, type,
vdev->v_nparity, id);
} else {
- (void) asprintf(&name, "%s-%" PRIu64, type, id);
+ (void) asprintf(&name, "%.*s-%" PRIu64, len, type, id);
}
vdev->v_name = name;
}
@@ -1321,13 +1342,13 @@ vdev_from_nvlist(spa_t *spa, uint64_t top_guid, const unsigned char *nvlist)
/* Add children if there are any. */
rc = nvlist_find(nvlist, ZPOOL_CONFIG_CHILDREN, DATA_TYPE_NVLIST_ARRAY,
- &nkids, &kids);
+ &nkids, &kids, NULL);
if (rc == 0) {
for (int i = 0; i < nkids; i++) {
uint64_t guid;
rc = nvlist_find(kids, ZPOOL_CONFIG_GUID,
- DATA_TYPE_UINT64, NULL, &guid);
+ DATA_TYPE_UINT64, NULL, &guid, NULL);
if (rc != 0)
return (rc);
rc = vdev_init(guid, kids, &vdev);
@@ -1358,11 +1379,11 @@ vdev_init_from_label(spa_t *spa, const unsigned char *nvlist)
const unsigned char *vdevs;
if (nvlist_find(nvlist, ZPOOL_CONFIG_POOL_GUID, DATA_TYPE_UINT64,
- NULL, &pool_guid) ||
+ NULL, &pool_guid, NULL) ||
nvlist_find(nvlist, ZPOOL_CONFIG_TOP_GUID, DATA_TYPE_UINT64,
- NULL, &top_guid) ||
+ NULL, &top_guid, NULL) ||
nvlist_find(nvlist, ZPOOL_CONFIG_VDEV_TREE, DATA_TYPE_NVLIST,
- NULL, &vdevs)) {
+ NULL, &vdevs, NULL)) {
printf("ZFS: can't find vdev details\n");
return (ENOENT);
}
@@ -1429,13 +1450,13 @@ vdev_update_from_nvlist(uint64_t top_guid, const unsigned char *nvlist)
/* Update children if there are any. */
rc = nvlist_find(nvlist, ZPOOL_CONFIG_CHILDREN, DATA_TYPE_NVLIST_ARRAY,
- &nkids, &kids);
+ &nkids, &kids, NULL);
if (rc == 0) {
for (int i = 0; i < nkids; i++) {
uint64_t guid;
rc = nvlist_find(kids, ZPOOL_CONFIG_GUID,
- DATA_TYPE_UINT64, NULL, &guid);
+ DATA_TYPE_UINT64, NULL, &guid, NULL);
if (rc != 0)
break;
@@ -1460,11 +1481,11 @@ vdev_init_from_nvlist(spa_t *spa, const unsigned char *nvlist)
int rc, nkids;
if (nvlist_find(nvlist, ZPOOL_CONFIG_POOL_GUID, DATA_TYPE_UINT64,
- NULL, &pool_guid) ||
+ NULL, &pool_guid, NULL) ||
nvlist_find(nvlist, ZPOOL_CONFIG_VDEV_CHILDREN, DATA_TYPE_UINT64,
- NULL, &vdev_children) ||
+ NULL, &vdev_children, NULL) ||
nvlist_find(nvlist, ZPOOL_CONFIG_VDEV_TREE, DATA_TYPE_NVLIST,
- NULL, &vdevs)) {
+ NULL, &vdevs, NULL)) {
printf("ZFS: can't find vdev details\n");
return (ENOENT);
}
@@ -1476,7 +1497,7 @@ vdev_init_from_nvlist(spa_t *spa, const unsigned char *nvlist)
spa->spa_root_vdev->v_nchildren = vdev_children;
rc = nvlist_find(vdevs, ZPOOL_CONFIG_CHILDREN, DATA_TYPE_NVLIST_ARRAY,
- &nkids, &kids);
+ &nkids, &kids, NULL);
/*
* MOS config has at least one child for root vdev.
@@ -1489,7 +1510,7 @@ vdev_init_from_nvlist(spa_t *spa, const unsigned char *nvlist)
vdev_t *vdev;
rc = nvlist_find(kids, ZPOOL_CONFIG_GUID, DATA_TYPE_UINT64,
- NULL, &guid);
+ NULL, &guid, NULL);
if (rc != 0)
break;
vdev = vdev_find(guid);
@@ -1837,7 +1858,7 @@ vdev_label_read_config(vdev_t *vd, uint64_t txg)
nvlist = (const unsigned char *) label->vp_nvlist + 4;
error = nvlist_find(nvlist, ZPOOL_CONFIG_POOL_TXG,
- DATA_TYPE_UINT64, NULL, &label_txg);
+ DATA_TYPE_UINT64, NULL, &label_txg, NULL);
if (error != 0 || label_txg == 0) {
memcpy(nvl, nvlist, nvl_size);
goto done;
@@ -1852,7 +1873,7 @@ vdev_label_read_config(vdev_t *vd, uint64_t txg)
* because we can get bad value from BIOS.
*/
if (nvlist_find(nvlist, ZPOOL_CONFIG_ASIZE,
- DATA_TYPE_UINT64, NULL, &asize) == 0) {
+ DATA_TYPE_UINT64, NULL, &asize, NULL) == 0) {
vd->v_psize = asize +
VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE;
}
@@ -1905,7 +1926,7 @@ vdev_probe(vdev_phys_read_t *phys_read, void *read_priv, spa_t **spap)
uint64_t pool_txg, pool_guid;
const char *pool_name;
const unsigned char *features;
- int rc;
+ int rc, namelen;
/*
* Load the vdev label and figure out which
@@ -1926,7 +1947,7 @@ vdev_probe(vdev_phys_read_t *phys_read, void *read_priv, spa_t **spap)
return (EIO);
if (nvlist_find(nvlist, ZPOOL_CONFIG_VERSION, DATA_TYPE_UINT64,
- NULL, &val) != 0) {
+ NULL, &val, NULL) != 0) {
free(nvlist);
return (EIO);
}
@@ -1940,14 +1961,14 @@ vdev_probe(vdev_phys_read_t *phys_read, void *read_priv, spa_t **spap)
/* Check ZFS features for read */
if (nvlist_find(nvlist, ZPOOL_CONFIG_FEATURES_FOR_READ,
- DATA_TYPE_NVLIST, NULL, &features) == 0 &&
+ DATA_TYPE_NVLIST, NULL, &features, NULL) == 0 &&
nvlist_check_features_for_read(features) != 0) {
free(nvlist);
return (EIO);
}
if (nvlist_find(nvlist, ZPOOL_CONFIG_POOL_STATE, DATA_TYPE_UINT64,
- NULL, &val) != 0) {
+ NULL, &val, NULL) != 0) {
free(nvlist);
return (EIO);
}
@@ -1959,11 +1980,11 @@ vdev_probe(vdev_phys_read_t *phys_read, void *read_priv, spa_t **spap)
}
if (nvlist_find(nvlist, ZPOOL_CONFIG_POOL_TXG, DATA_TYPE_UINT64,
- NULL, &pool_txg) != 0 ||
+ NULL, &pool_txg, NULL) != 0 ||
nvlist_find(nvlist, ZPOOL_CONFIG_POOL_GUID, DATA_TYPE_UINT64,
- NULL, &pool_guid) != 0 ||
+ NULL, &pool_guid, NULL) != 0 ||
nvlist_find(nvlist, ZPOOL_CONFIG_POOL_NAME, DATA_TYPE_STRING,
- NULL, &pool_name) != 0) {
+ NULL, &pool_name, &namelen) != 0) {
/*
* Cache and spare devices end up here - just ignore
* them.
@@ -1977,9 +1998,19 @@ vdev_probe(vdev_phys_read_t *phys_read, void *read_priv, spa_t **spap)
*/
spa = spa_find_by_guid(pool_guid);
if (spa == NULL) {
+ char *name;
+
nvlist_find(nvlist, ZPOOL_CONFIG_VDEV_CHILDREN,
- DATA_TYPE_UINT64, NULL, &vdev_children);
- spa = spa_create(pool_guid, pool_name);
+ DATA_TYPE_UINT64, NULL, &vdev_children, NULL);
+ name = malloc(namelen + 1);
+ if (name == NULL) {
+ free(nvlist);
+ return (ENOMEM);
+ }
+ bcopy(pool_name, name, namelen);
+ name[namelen] = '\0';
+ spa = spa_create(pool_guid, name);
+ free(name);
if (spa == NULL) {
free(nvlist);
return (ENOMEM);
@@ -1996,7 +2027,7 @@ vdev_probe(vdev_phys_read_t *phys_read, void *read_priv, spa_t **spap)
* disks etc).
*/
if (nvlist_find(nvlist, ZPOOL_CONFIG_GUID, DATA_TYPE_UINT64,
- NULL, &guid) != 0) {
+ NULL, &guid, NULL) != 0) {
free(nvlist);
return (EIO);
}
diff --git a/usr/src/cmd/sgs/error/common/errorinput.c b/usr/src/cmd/sgs/error/common/errorinput.c
index eae36879aa..1f02ab6923 100644
--- a/usr/src/cmd/sgs/error/common/errorinput.c
+++ b/usr/src/cmd/sgs/error/common/errorinput.c
@@ -25,8 +25,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <ctype.h>
#include <string.h>
@@ -129,7 +127,7 @@ erroradd(int errorlength, char **errorv, Errorclass errorclass,
#ifdef FULLDEBUG
if (errorclass != C_TRUE)
printf("The 2nd word, \"%s\" is not a number.\n",
- errorv[1]);
+ errorv[1]);
#endif
}
if (errorlength > 0) {
@@ -143,10 +141,10 @@ erroradd(int errorlength, char **errorv, Errorclass errorclass,
newerror->error_s_class = errorsubclass;
switch (newerror->error_e_class = discardit(newerror)) {
case C_SYNC: nsyncerrors++; break;
- case C_DISCARD: ndiscard++; break;
+ case C_DISCARD: ndiscard++; break;
case C_NULLED: nnulled++; break;
case C_NONSPEC: nnonspec++; break;
- case C_THISFILE: nthisfile++; break;
+ case C_THISFILE: nthisfile++; break;
case C_TRUE: ntrue++; break;
case C_UNKNOWN: nunknown++; break;
case C_IGNORE: nignore++; break;
@@ -315,7 +313,7 @@ Errorclass
lint0(void)
{
char **nwordv;
- char *line, *file;
+ char *line, *file;
/*
* Attempt a match for the new lint style normal compiler
* error messages, of the form
@@ -453,8 +451,8 @@ f77(void)
return (C_UNKNOWN);
if ((lastchar(wordv[6]) == ':') &&
((wordvcmp(wordv+1, 3, F77_fatal) == 0) ||
- (wordvcmp(wordv+1, 3, F77_error) == 0) ||
- (wordvcmp(wordv+1, 3, F77_warning) == 0))) {
+ (wordvcmp(wordv+1, 3, F77_error) == 0) ||
+ (wordvcmp(wordv+1, 3, F77_warning) == 0))) {
language = INF77;
nwordv = wordvsplice(2, wordc, wordv+1);
nwordv[0] = wordv[6];
@@ -564,10 +562,10 @@ mod2(void)
*/
if (((strcmp(wordv[1], "!!!") == 0) || /* early version */
(strcmp(wordv[1], "File") == 0)) && /* later version */
- (lastchar(wordv[2]) == ',') && /* file name */
- (strcmp(wordv[3], "line") == 0) &&
- (isdigit(firstchar(wordv[4]))) && /* line number */
- (lastchar(wordv[4]) == ':')) { /* line number */
+ (lastchar(wordv[2]) == ',') && /* file name */
+ (strcmp(wordv[3], "line") == 0) &&
+ (isdigit(firstchar(wordv[4]))) && /* line number */
+ (lastchar(wordv[4]) == ':')) { /* line number */
clob_last(wordv[2], '\0'); /* drop last , on file name */
clob_last(wordv[4], '\0'); /* drop last : on line number */
wordv[3] = wordv[2]; /* file name on top of "line" */
@@ -596,10 +594,10 @@ sunf77(void)
(strcmp(wordv[2], "line") == 0) &&
(isdigit(firstchar(wordv[3]))) &&
(lastchar(wordv[3]) == ':') &&
- ((strcmp(wordv[4], "Error:") == 0) ||
- (strcmp(wordv[4], "Warning:") == 0) ||
- ((strcmp(wordv[4], "ANSI") == 0) &&
- (strcmp(wordv[5], "extension:") == 0)))) {
+ ((strcmp(wordv[4], "Error:") == 0) ||
+ (strcmp(wordv[4], "Warning:") == 0) ||
+ ((strcmp(wordv[4], "ANSI") == 0) &&
+ (strcmp(wordv[5], "extension:") == 0)))) {
clob_last(wordv[1], '\0'); /* drop last , */
clob_last(wordv[1], '\0'); /* drop last " */
wordv[1]++; /* drop first " */
diff --git a/usr/src/cmd/sgs/error/common/errorsubr.c b/usr/src/cmd/sgs/error/common/errorsubr.c
index e2d0828a4f..17bc104c01 100644
--- a/usr/src/cmd/sgs/error/common/errorsubr.c
+++ b/usr/src/cmd/sgs/error/common/errorsubr.c
@@ -101,10 +101,12 @@ int
position(char *string, char ch)
{
int i;
- if (string)
- for (i = 1; *string; string++, i++) {
- if (*string == ch)
- return (i);
+
+ if (string) {
+ for (i = 1; *string; string++, i++) {
+ if (*string == ch)
+ return (i);
+ }
}
return (-1);
}
@@ -116,13 +118,14 @@ substitute(char *string, char chold, char chnew)
{
char *cp = string;
- if (cp)
- while (*cp) {
- if (*cp == chold) {
- *cp = chnew;
- break;
+ if (cp) {
+ while (*cp) {
+ if (*cp == chold) {
+ *cp = chnew;
+ break;
+ }
+ cp++;
}
- cp++;
}
return (string);
}
@@ -283,7 +286,7 @@ wordvprint(FILE *fyle, int wordc, char *wordv[])
void
wordvbuild(char *string, int *r_wordc, char ***r_wordv)
{
- char *cp;
+ char *cp;
char *saltedbuffer;
char **wordv;
int wordcount;
diff --git a/usr/src/cmd/sgs/error/common/errortouch.c b/usr/src/cmd/sgs/error/common/errortouch.c
index 6773fc0476..fcc3ce9499 100644
--- a/usr/src/cmd/sgs/error/common/errortouch.c
+++ b/usr/src/cmd/sgs/error/common/errortouch.c
@@ -164,14 +164,14 @@ filenames(int nfiles, Eptr **files)
if (nfiles) {
someerrors++;
(void) fprintf(stdout, terse
- ? "%d file%s"
- : "%d file%s contain%s errors",
- nfiles, plural(nfiles), verbform(nfiles));
+ ? "%d file%s"
+ : "%d file%s contain%s errors",
+ nfiles, plural(nfiles), verbform(nfiles));
if (!terse) {
FILEITERATE(fi, 1) {
(void) fprintf(stdout, "%s\"%s\" (%d)",
- sep, (*files[fi])->error_text[0],
- files[fi+1] - files[fi]);
+ sep, (*files[fi])->error_text[0],
+ files[fi+1] - files[fi]);
sep = ", ";
}
}
@@ -201,10 +201,10 @@ nopertain(Eptr **files)
someerrors++;
if (terse) {
(void) fprintf(stdout, "\t%d %s errors NOT PRINTED\n",
- class_count[type], class_table[type]);
+ class_count[type], class_table[type]);
} else {
(void) fprintf(stdout, "\n\t%d %s errors follow\n",
- class_count[type], class_table[type]);
+ class_count[type], class_table[type]);
EITERATE(erpp, files, 0) {
errorp = *erpp;
if (errorp->error_e_class == type) {
@@ -232,9 +232,9 @@ touchfiles(int nfiles, Eptr **files, int *r_edargc, char ***r_edargv)
name = (*files[fi])->error_text[0];
spread = files[fi+1] - files[fi];
(void) fprintf(stdout, terse
- ? "\"%s\" has %d error%s, "
- : "\nFile \"%s\" has %d error%s.\n",
- name, spread, plural(spread));
+ ? "\"%s\" has %d error%s, "
+ : "\nFile \"%s\" has %d error%s.\n",
+ name, spread, plural(spread));
/*
* First, iterate through all error messages in this file
* to see how many of the error messages really will
@@ -336,9 +336,9 @@ settotouch(char *name)
if (query) {
switch (touchstatus = inquire(terse
- ? "Touch? "
- : "Do you want to touch file \"%s\"? ",
- name)) {
+ ? "Touch? "
+ : "Do you want to touch file \"%s\"? ",
+ name)) {
case Q_NO:
case Q_no:
return (dest);
@@ -351,23 +351,23 @@ settotouch(char *name)
case F_NOTREAD:
dest = TOSTDOUT;
(void) fprintf(stdout, terse
- ? "\"%s\" unreadable\n"
- : "File \"%s\" is unreadable\n",
- name);
+ ? "\"%s\" unreadable\n"
+ : "File \"%s\" is unreadable\n",
+ name);
break;
case F_NOTWRITE:
dest = TOSTDOUT;
(void) fprintf(stdout, terse
- ? "\"%s\" unwritable\n"
- : "File \"%s\" is unwritable\n",
- name);
+ ? "\"%s\" unwritable\n"
+ : "File \"%s\" is unwritable\n",
+ name);
break;
case F_NOTEXIST:
dest = TOSTDOUT;
(void) fprintf(stdout,
terse ? "\"%s\" not found\n" :
- "Can't find file \"%s\" to insert error "
- "messages into.\n",
+ "Can't find file \"%s\" to insert error "
+ "messages into.\n",
name);
break;
default:
@@ -389,9 +389,9 @@ diverterrors(char *name, int dest, Eptr **files, int ix,
if ((nerrors != nterrors) && (!previewed)) {
(void) fprintf(stdout, terse
- ? "Uninserted errors\n"
- : ">>Uninserted errors for file \"%s\" follow.\n",
- name);
+ ? "Uninserted errors\n"
+ : ">>Uninserted errors for file \"%s\" follow.\n",
+ name);
}
EITERATE(erpp, files, ix) {
@@ -422,7 +422,7 @@ oktotouch(char *filename)
extern char *suffixlist;
char *src;
char *pat;
- char *osrc;
+ char *osrc;
pat = suffixlist;
if (pat == 0)
@@ -558,8 +558,8 @@ text(Eptr p, boolean use_all)
(void) fputs(lang_table[p->error_language].lang_incomment,
n_touchedfile);
(void) fprintf(n_touchedfile, "%d [%s] ",
- p->error_line,
- lang_table[p->error_language].lang_name);
+ p->error_line,
+ lang_table[p->error_language].lang_name);
wordvprint(n_touchedfile, p->error_lgtext-offset, p->error_text+offset);
(void) fputs(lang_table[p->error_language].lang_outcomment,
n_touchedfile);
@@ -605,8 +605,8 @@ writetouched(int overwrite)
tmpfile = NULL;
if ((localfile = fopen(o_name, "w")) == NULL) {
(void) fprintf(stderr,
- "%s: Can't open file \"%s\" to overwrite.\n",
- processname, o_name);
+ "%s: Can't open file \"%s\" to overwrite.\n",
+ processname, o_name);
botch++;
}
if ((tmpfile = fopen(n_name, "r")) == NULL) {
diff --git a/usr/src/cmd/sgs/rtld/common/a.out.c b/usr/src/cmd/sgs/rtld/common/a.out.c
index 6ea37918ad..693b4f59bc 100644
--- a/usr/src/cmd/sgs/rtld/common/a.out.c
+++ b/usr/src/cmd/sgs/rtld/common/a.out.c
@@ -356,7 +356,7 @@ aout_find_com(struct nlist *sp, const char *name)
(void) strcpy(rs->rtc_sp->n_un.n_name, name);
rs->rtc_sp->n_type = N_COMM;
if ((rs->rtc_sp->n_value =
- (long)calloc(rs->rtc_sp->n_value, 1)) == NULL)
+ (long)calloc(rs->rtc_sp->n_value, 1)) == (long)NULL)
return (NULL);
return (rs->rtc_sp);
}
@@ -419,7 +419,7 @@ aout_findsb(const char *aname, Rt_map *lmp, int flag)
if (*name++ == '\0')
return (sp); /* found */
}
- if (p->next == NULL)
+ if (p->next == 0)
return (NULL); /* not found */
else
continue;
diff --git a/usr/src/cmd/sgs/rtld/common/cache_a.out.c b/usr/src/cmd/sgs/rtld/common/cache_a.out.c
index 0afdcdb5e5..994edaa2fd 100644
--- a/usr/src/cmd/sgs/rtld/common/cache_a.out.c
+++ b/usr/src/cmd/sgs/rtld/common/cache_a.out.c
@@ -38,16 +38,16 @@
#include "_rtld.h"
#include "msg.h"
-static int stol();
-static int rest_ok();
-static int verscmp();
-static void fix_lo();
-static int extract_name();
-static int hash();
+static int stol(char *, char, char **, int *);
+static int rest_ok(char *);
+static int verscmp(const char *, const char *);
+static void fix_lo(struct db *);
+static int extract_name(char **);
+static int hash(char *, int, int);
-static struct link_object *get_lo();
-static struct dbd *new_dbd();
-static struct db *find_so();
+static struct link_object *get_lo(struct db *, char *, int, int, int);
+static struct dbd *new_dbd(struct dbd **, struct db *);
+static struct db *find_so(const char *);
#define SKIP_DOT(str) ((*str == '.') ? ++str : str)
#define EMPTY(str) ((str == NULL) || (*str == '\0'))
@@ -62,9 +62,7 @@ static struct dbd *dbd_head = NULL; /* head of data bases */
* but the highest minor number
*/
char *
-ask_db(dbp, file)
- struct db *dbp;
- const char *file;
+ask_db(struct db *dbp, const char *file)
{
char *libname, *n;
char *mnp;
@@ -82,7 +80,7 @@ ask_db(dbp, file)
if ((libname = malloc(liblen + 1)) == 0)
return (NULL);
(void) strncpy(libname, n, liblen);
- libname[liblen] = NULL;
+ libname[liblen] = '\0';
if (strncmp(MSG_ORIG(MSG_FIL_DOTSODOT), (n + liblen),
MSG_FIL_DOTSODOT_SIZE))
@@ -245,7 +243,7 @@ find_so(const char *ds)
*/
index = hash(cp, cplen, m);
ep = &(dbp->db_hash[index]);
- if (ep->dbe_lop == NULL) {
+ if (ep->dbe_lop == 0) {
ep->dbe_lop = (long)get_lo(dbp, cp,
cplen, m, to_min);
/* LINTED */
@@ -278,7 +276,7 @@ find_so(const char *ds)
dp->d_name);
break;
}
- if (ep->dbe_next == NULL) {
+ if (ep->dbe_next == 0) {
ep->dbe_next = RELPTR(dbp,
calloc(sizeof (struct dbe), 1));
/* LINTED */
@@ -302,14 +300,15 @@ find_so(const char *ds)
/*
* Allocate and fill in the fields for a link_object
+ * Arguments:
+ * struct db *dbp; data base
+ * char *cp; ptr. to X of libX
+ * int cplen; length of X
+ * int m; major version
+ * int n; index to minor version
*/
static struct link_object *
-get_lo(dbp, cp, cplen, m, n)
- struct db *dbp; /* data base */
- char *cp; /* ptr. to X of libX */
- int cplen; /* length of X */
- int m; /* major version */
- int n; /* index to minor version */
+get_lo(struct db *dbp, char *cp, int cplen, int m, int n)
{
struct link_object *lop; /* link_object to be returned */
struct link_object *tlop; /* working copy of the above */
@@ -353,8 +352,7 @@ get_lo(dbp, cp, cplen, m, n)
* length of X
*/
static int
-extract_name(name)
- char **name;
+extract_name(char **name)
{
char *ls; /* string after LIB root */
char *dp; /* string before first delimiter */
@@ -375,8 +373,7 @@ extract_name(name)
* but only one will be chosen.
*/
static void
-fix_lo(dbp)
- struct db *dbp;
+fix_lo(struct db *dbp)
{
int i; /* loop temporary */
int dirlen = strlen(&AP(dbp)[dbp->db_name]);
@@ -408,11 +405,12 @@ fix_lo(dbp)
/*
* Allocate a new dbd, append it after dbdpp and set the dbd_dbp to dbp.
+ * Arguments:
+ * struct dbd **dbdpp; insertion point
+ * struct db *dbp; db associated with this dbd
*/
static struct dbd *
-new_dbd(dbdpp, dbp)
- struct dbd **dbdpp; /* insertion point */
- struct db *dbp; /* db associated with this dbd */
+new_dbd(struct dbd **dbdpp, struct db *dbp)
{
struct dbd *dbdp; /* working dbd ptr. */
@@ -426,12 +424,13 @@ new_dbd(dbdpp, dbp)
/*
* Calculate hash index for link object.
* This is based on X.major from libX.so.major.minor.
+ * Arguments:
+ * char *np; X of libX
+ * int nchrs; no of chrs. to hash on
+ * int m; the major version
*/
static int
-hash(np, nchrs, m)
- char *np; /* X of libX */
- int nchrs; /* no of chrs. to hash on */
- int m; /* the major version */
+hash(char *np, int nchrs, int m)
{
int h; /* for loop counter */
char *cp; /* working (char *) ptr */
@@ -447,8 +446,7 @@ hash(np, nchrs, m)
* Test whether the string is of digit[.digit]* format
*/
static int
-rest_ok(str)
- char *str; /* input string */
+rest_ok(char *str)
{
int dummy; /* integer place holder */
int legal = 1; /* return flag */
@@ -509,14 +507,15 @@ verscmp(const char *c1p, const char *c2p)
* as a decimal digit. It stops interpreting when it reaches a delimiter or
* when character does not represent a digit. In the first case it returns
* success and the latter failure.
+ * Arguments:
+ * char *cp; ptr to input string
+ * char delimit; delimiter
+ * char **ptr; left pointing to next del. or
+ * illegal character
+ * int *i; digit that the string represents
*/
static int
-stol(cp, delimit, ptr, i)
- char *cp; /* ptr to input string */
- char delimit; /* delimiter */
- char **ptr; /* left pointing to next del. or */
- /* illegal character */
- int *i; /* digit that the string represents */
+stol(char *cp, char delimit, char **ptr, int *i)
{
int c = 0; /* current char */
int n = 0; /* working copy of i */
diff --git a/usr/src/pkg/manifests/system-test-ostest.mf b/usr/src/pkg/manifests/system-test-ostest.mf
index e7de55cfe6..1abad62de8 100644
--- a/usr/src/pkg/manifests/system-test-ostest.mf
+++ b/usr/src/pkg/manifests/system-test-ostest.mf
@@ -13,6 +13,7 @@
# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
# Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
# Copyright 2020 Joyent, Inc.
+# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
#
set name=pkg.fmri value=pkg:/system/test/ostest@$(PKGVERS)
@@ -91,6 +92,8 @@ file path=opt/os-tests/tests/sockfs/conn mode=0555
file path=opt/os-tests/tests/sockfs/dgram mode=0555
file path=opt/os-tests/tests/sockfs/drop_priv mode=0555
file path=opt/os-tests/tests/sockfs/nosignal mode=0555
+file path=opt/os-tests/tests/sockfs/rights.32 mode=0555
+file path=opt/os-tests/tests/sockfs/rights.64 mode=0555
file path=opt/os-tests/tests/sockfs/sockpair mode=0555
file path=opt/os-tests/tests/spoof-ras mode=0555
file path=opt/os-tests/tests/stress/dladm-kstat mode=0555
diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run
index 322c26d6ff..bcb8468ec5 100644
--- a/usr/src/test/os-tests/runfiles/default.run
+++ b/usr/src/test/os-tests/runfiles/default.run
@@ -12,6 +12,7 @@
#
# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright 2020 Joyent, Inc.
+# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
#
[DEFAULT]
@@ -72,7 +73,8 @@ tests = ['runtests.32', 'runtests.64']
[/opt/os-tests/tests/sockfs]
user = root
-tests = ['conn', 'dgram', 'drop_priv', 'nosignal', 'sockpair']
+tests = ['conn', 'dgram', 'drop_priv', 'nosignal', 'rights.32', 'rights.64',
+ 'sockpair']
[/opt/os-tests/tests/pf_key]
user = root
diff --git a/usr/src/test/os-tests/tests/sockfs/Makefile b/usr/src/test/os-tests/tests/sockfs/Makefile
index 638250a400..267c8bbe4e 100644
--- a/usr/src/test/os-tests/tests/sockfs/Makefile
+++ b/usr/src/test/os-tests/tests/sockfs/Makefile
@@ -13,16 +13,18 @@
# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright 2017 Gordon W. Ross
# Copyright (c) 2018, Joyent, Inc.
+# Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
#
include $(SRC)/cmd/Makefile.cmd
include $(SRC)/test/Makefile.com
-PROG = conn dgram drop_priv nosignal sockpair
-
-LINTS = $(PROGS:%=%.ln)
+PROG = conn dgram drop_priv nosignal sockpair \
+ rights.32 rights.64
LDLIBS += -lsocket
+LDLIBS64 += -lsocket
+
CSTD = $(CSTD_GNU99)
CPPFLAGS += -D_XOPEN_SOURCE=600 -D__EXTENSIONS__
@@ -30,7 +32,8 @@ CPPFLAGS += -D_XOPEN_SOURCE=600 -D__EXTENSIONS__
SMOFF += all_func_returns
nosignal := LDLIBS += -lnsl
-nosignal.ln := LDLIBS += -lnsl
+rights.32 := LDLIBS += -lproc
+rights.64 := LDLIBS64 += -lproc
ROOTOPTPKG = $(ROOT)/opt/os-tests
TESTDIR = $(ROOTOPTPKG)/tests/sockfs
@@ -42,8 +45,6 @@ all: $(PROG)
install: $(CMDS)
-lint: $(LINTS)
-
clobber: clean
-$(RM) $(PROG)
@@ -51,11 +52,16 @@ clean:
$(CMDS): $(TESTDIR) $(PROG)
-%.ln : %.c
- $(LINT.c) $*.c $(UTILS) $(LDLIBS)
-
$(TESTDIR):
$(INS.dir)
$(TESTDIR)/%: %
$(INS.file)
+
+%.64: %.c
+ $(LINK64.c) -o $@ $< $(LDLIBS64)
+ $(POST_PROCESS)
+
+%.32: %.c
+ $(LINK.c) -o $@ $< $(LDLIBS)
+ $(POST_PROCESS)
diff --git a/usr/src/test/os-tests/tests/sockfs/rights.c b/usr/src/test/os-tests/tests/sockfs/rights.c
new file mode 100644
index 0000000000..97987d62c5
--- /dev/null
+++ b/usr/src/test/os-tests/tests/sockfs/rights.c
@@ -0,0 +1,700 @@
+/*
+ * 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 2020 OmniOS Community Edition (OmniOSce) Association.
+ */
+
+/*
+ * Test file descriptor passing via SCM_RIGHTS, and in particular what happens
+ * on message truncation in terms of the represented size of the data in the
+ * control message. Ensure that no file descriptors are leaked - the kernel
+ * must close any that would not fit in the available buffer space and the
+ * userland application must close the rest.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <libproc.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <alloca.h>
+#include <err.h>
+
+static boolean_t debug;
+
+typedef struct cmsg_test {
+ char *name; /* Name of the test */
+ uint_t send; /* Number of FDs to send */
+ uint_t recv; /* Size receive buffer for this number of FDs */
+ size_t predata; /* Prepend dummy cmsg of this size */
+ int bufsize; /* Explicitly set receive buffer size. */
+ /* Overrides 'recv' if non-zero */
+ uint_t x_controllen; /* Expected received msg_controllen */
+ uint_t x_cmsg_datalen; /* Expected received cmsg data length */
+ uint32_t x_flags; /* Expected received msf_flags */
+} cmsg_test_t;
+
+static cmsg_test_t tests[] = {
+ {
+ .name = "send 1, recv 1",
+ .send = 1,
+ .recv = 1,
+ .predata = 0,
+ .bufsize = 0,
+ .x_controllen = 16,
+ .x_cmsg_datalen = 4,
+ .x_flags = 0,
+ },
+ {
+ .name = "send 10, recv 10",
+ .send = 10,
+ .recv = 10,
+ .predata = 0,
+ .bufsize = 0,
+ .x_controllen = 52,
+ .x_cmsg_datalen = 40,
+ .x_flags = 0,
+ },
+ {
+ .name = "send 2, recv 1",
+ .send = 2,
+ .recv = 1,
+ .predata = 0,
+ .bufsize = 0,
+ .x_controllen = 16,
+ .x_cmsg_datalen = 4,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, buffer 5",
+ .send = 2,
+ .recv = 1,
+ .predata = 0,
+ .bufsize = sizeof (int) * 2 - 3,
+ .x_controllen = 17,
+ .x_cmsg_datalen = 5,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, buffer 6",
+ .send = 2,
+ .recv = 1,
+ .predata = 0,
+ .bufsize = sizeof (int) * 2 - 2,
+ .x_controllen = 18,
+ .x_cmsg_datalen = 6,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, buffer 7",
+ .send = 2,
+ .recv = 1,
+ .predata = 0,
+ .bufsize = sizeof (int) * 2 - 1,
+ .x_controllen = 19,
+ .x_cmsg_datalen = 7,
+ .x_flags = MSG_CTRUNC,
+ },
+
+ /* Tests where there is no room allowed for data */
+
+ {
+ .name = "send 2, recv 0, hdronly",
+ .send = 2,
+ .recv = 0,
+ .predata = 0,
+ .bufsize = 0,
+ .x_controllen = 12,
+ .x_cmsg_datalen = 0,
+ .x_flags = MSG_CTRUNC,
+ },
+
+ {
+ .name = "send 2, recv 0, hdr - 1",
+ .send = 2,
+ .recv = 0,
+ .predata = 0,
+ .bufsize = -1,
+ .x_controllen = 11,
+ .x_cmsg_datalen = 0,
+ .x_flags = MSG_CTRUNC,
+ },
+
+ {
+ .name = "send 2, recv 0, hdr - 5",
+ .send = 2,
+ .recv = 0,
+ .predata = 0,
+ .bufsize = -5,
+ .x_controllen = 7,
+ .x_cmsg_datalen = 0,
+ .x_flags = MSG_CTRUNC,
+ },
+
+ /* Tests where SCM_RIGHTS is not the first message */
+
+ {
+ .name = "send 1, recv 1, pre 8",
+ .send = 1,
+ .recv = 1,
+ .predata = 8,
+ .bufsize = 0,
+ .x_controllen = 36,
+ .x_cmsg_datalen = 4,
+ .x_flags = 0,
+ },
+ {
+ .name = "send 1, recv 1, pre 7",
+ .send = 1,
+ .recv = 1,
+ .predata = 7,
+ .bufsize = 0,
+ .x_controllen = 35,
+ .x_cmsg_datalen = 4,
+ .x_flags = 0,
+ },
+ {
+ .name = "send 1, recv 1, pre 6",
+ .send = 1,
+ .recv = 1,
+ .predata = 6,
+ .bufsize = 0,
+ .x_controllen = 34,
+ .x_cmsg_datalen = 4,
+ .x_flags = 0,
+ },
+ {
+ .name = "send 1, recv 1, pre 5",
+ .send = 1,
+ .recv = 1,
+ .predata = 5,
+ .bufsize = 0,
+ .x_controllen = 33,
+ .x_cmsg_datalen = 4,
+ .x_flags = 0,
+ },
+
+ {
+ .name = "send 2, recv 1, pre 8",
+ .send = 2,
+ .recv = 1,
+ .predata = 8,
+ .bufsize = 0,
+ .x_controllen = 36,
+ .x_cmsg_datalen = 8,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, pre 7",
+ .send = 2,
+ .recv = 1,
+ .predata = 7,
+ .bufsize = 0,
+ .x_controllen = 36,
+ .x_cmsg_datalen = 8,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, pre 6",
+ .send = 2,
+ .recv = 1,
+ .predata = 6,
+ .bufsize = 0,
+ .x_controllen = 36,
+ .x_cmsg_datalen = 8,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, pre 5",
+ .send = 2,
+ .recv = 1,
+ .predata = 5,
+ .bufsize = 0,
+ .x_controllen = 36,
+ .x_cmsg_datalen = 8,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, pre 4",
+ .send = 2,
+ .recv = 1,
+ .predata = 4,
+ .bufsize = 0,
+ .x_controllen = 32,
+ .x_cmsg_datalen = 8,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, pre 3",
+ .send = 2,
+ .recv = 1,
+ .predata = 3,
+ .bufsize = 0,
+ .x_controllen = 32,
+ .x_cmsg_datalen = 8,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, pre 2",
+ .send = 2,
+ .recv = 1,
+ .predata = 2,
+ .bufsize = 0,
+ .x_controllen = 32,
+ .x_cmsg_datalen = 8,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, pre 1",
+ .send = 2,
+ .recv = 1,
+ .predata = 1,
+ .bufsize = 0,
+ .x_controllen = 32,
+ .x_cmsg_datalen = 8,
+ .x_flags = MSG_CTRUNC,
+ },
+
+ {
+ .name = "send 2, recv 1, pre 8, buffer 5",
+ .send = 2,
+ .recv = 1,
+ .predata = 8,
+ .bufsize = sizeof (int) * 2 - 3,
+ .x_controllen = 37,
+ .x_cmsg_datalen = 8,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, pre 8, buffer 6",
+ .send = 2,
+ .recv = 1,
+ .predata = 8,
+ .bufsize = sizeof (int) * 2 - 2,
+ .x_controllen = 38,
+ .x_cmsg_datalen = 8,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 2, recv 1, pre 8, buffer 7",
+ .send = 2,
+ .recv = 1,
+ .predata = 8,
+ .bufsize = sizeof (int) * 2 - 1,
+ .x_controllen = 39,
+ .x_cmsg_datalen = 8,
+ .x_flags = MSG_CTRUNC,
+ },
+ {
+ .name = "send 10, recv 1, pre 8",
+ .send = 10,
+ .recv = 1,
+ .predata = 8,
+ .bufsize = 0,
+ .x_controllen = 36,
+ .x_cmsg_datalen = 24,
+ .x_flags = MSG_CTRUNC,
+ },
+
+ /* End of tests */
+
+ {
+ .name = NULL
+ }
+};
+
+static int sock = -1, testfd = -1, cfd = -1;
+static int fdcount;
+
+static int
+fdwalkcb(const prfdinfo_t *info, void *arg)
+{
+ if (!S_ISDIR(info->pr_mode) && info->pr_fd > 2 &&
+ info->pr_fd != sock && info->pr_fd != testfd &&
+ info->pr_fd != cfd) {
+ if (debug) {
+ fprintf(stderr, "%s: unexpected fd: %d\n",
+ (char *)arg, info->pr_fd);
+ }
+ fdcount++;
+ }
+
+ return (0);
+
+}
+
+static void
+check_fds(char *tag)
+{
+ fdcount = 0;
+ proc_fdwalk(getpid(), fdwalkcb, tag);
+}
+
+static void
+send_and_wait(pid_t pid, sigset_t *set, int osig, int isig)
+{
+ int sig;
+
+ if (osig > 0)
+ kill(pid, osig);
+
+ if (isig > 0) {
+ if (sigwait(set, &sig) != 0) {
+ err(EXIT_FAILURE,
+ "sigwait failed waiting for %d", isig);
+ }
+ if (sig == SIGINT) {
+ exit(1);
+ }
+ if (sig != isig) {
+ err(EXIT_FAILURE,
+ "sigwait returned unexpected signal %d", sig);
+ }
+ }
+}
+
+static void
+sendtest(cmsg_test_t *t)
+{
+ struct msghdr msg;
+ struct cmsghdr *cm;
+ struct iovec iov;
+ ssize_t nbytes;
+ char c = '*';
+ int i, *p;
+
+ bzero(&msg, sizeof (msg));
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+
+ iov.iov_base = &c;
+ iov.iov_len = sizeof (c);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ msg.msg_flags = 0;
+
+ msg.msg_controllen = CMSG_SPACE(sizeof (int) * t->send);
+
+ if (t->predata > 0) {
+ /* A dummy cmsg will be inserted at the head of the data */
+ msg.msg_controllen += CMSG_SPACE(t->predata);
+ }
+
+ msg.msg_control = alloca(msg.msg_controllen);
+ bzero(msg.msg_control, msg.msg_controllen);
+
+ cm = CMSG_FIRSTHDR(&msg);
+
+ if (t->predata > 0) {
+ /* Insert the dummy cmsg */
+ cm->cmsg_len = CMSG_LEN(t->predata);
+ cm->cmsg_level = SOL_SOCKET;
+ cm->cmsg_type = 0;
+ cm = CMSG_NXTHDR(&msg, cm);
+ }
+
+ cm->cmsg_len = CMSG_LEN(sizeof (int) * t->send);
+ cm->cmsg_level = SOL_SOCKET;
+ cm->cmsg_type = SCM_RIGHTS;
+
+ p = (int *)CMSG_DATA(cm);
+ for (i = 0; i < t->send; i++) {
+ int s = dup(testfd);
+ if (s == -1)
+ err(EXIT_FAILURE, "dup()");
+ *p++ = s;
+ }
+
+ if (debug)
+ printf("Sending: controllen=%u\n", msg.msg_controllen);
+
+ nbytes = sendmsg(cfd, &msg, 0);
+ if (nbytes == -1)
+ err(EXIT_FAILURE, "sendmsg()");
+
+ p = (int *)CMSG_DATA(cm);
+ for (i = 0; i < t->send; i++)
+ (void) close(*p++);
+}
+
+static int
+server(const char *sockpath, pid_t pid)
+{
+ struct sockaddr_un addr;
+ sigset_t set;
+ cmsg_test_t *t;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR2);
+ sigaddset(&set, SIGINT);
+
+ sock = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (sock == -1)
+ err(EXIT_FAILURE, "failed to create socket");
+ addr.sun_family = AF_UNIX;
+ strlcpy(addr.sun_path, sockpath, sizeof (addr.sun_path));
+ if (bind(sock, (struct sockaddr *)&addr, sizeof (addr)) == -1)
+ err(EXIT_FAILURE, "bind failed");
+ if (listen(sock, 0) == -1)
+ err(EXIT_FAILURE, "listen failed");
+
+ if ((testfd = open("/dev/null", O_RDONLY)) == -1)
+ err(EXIT_FAILURE, "/dev/null");
+
+ check_fds("server");
+
+ /* Signal the child to connect to the socket */
+ send_and_wait(pid, &set, SIGUSR1, SIGUSR2);
+
+ if ((cfd = accept(sock, NULL, 0)) == -1)
+ err(EXIT_FAILURE, "accept failed");
+
+ for (t = tests; t->name != NULL; t++) {
+ if (debug)
+ printf("\n>>> Starting test %s\n", t->name);
+
+ sendtest(t);
+ check_fds("server");
+
+ send_and_wait(pid, &set, SIGUSR1, SIGUSR2);
+ }
+
+ close(cfd);
+ close(testfd);
+ close(sock);
+
+ return (0);
+}
+
+static boolean_t pass;
+
+static void
+check(uint_t actual, uint_t expected, char *tag)
+{
+ if (actual != expected) {
+ fprintf(stderr, " !!!: "
+ "%1$s = %2$u(%2$#x) (expected %3$u(%3$#x))\n",
+ tag, actual, expected);
+ pass = _B_FALSE;
+ } else if (debug) {
+ fprintf(stderr, " : "
+ "%1$s = %2$u(%2$#x)\n",
+ tag, actual);
+ }
+}
+
+static boolean_t
+recvtest(cmsg_test_t *t)
+{
+ struct msghdr msg;
+ struct cmsghdr *cm;
+ struct iovec iov;
+ size_t bufsize;
+ ssize_t nbytes;
+ char c = '*';
+
+ bzero(&msg, sizeof (msg));
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+
+ iov.iov_base = &c;
+ iov.iov_len = sizeof (c);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ msg.msg_flags = 0;
+
+ /*
+ * If the test does not specify a receive buffer size, calculate one
+ * from the number of file descriptors to receive.
+ */
+ if (t->bufsize == 0) {
+ bufsize = sizeof (int) * t->recv;
+ bufsize = CMSG_SPACE(bufsize);
+ } else {
+ /*
+ * Use the specific buffer size provided but add in
+ * space for the header
+ */
+ bufsize = t->bufsize + CMSG_LEN(0);
+ }
+
+ if (t->predata > 0) {
+ /* A dummy cmsg will be found at the head of the data */
+ bufsize += CMSG_SPACE(t->predata);
+ }
+
+ msg.msg_controllen = bufsize;
+ msg.msg_control = alloca(bufsize);
+ bzero(msg.msg_control, msg.msg_controllen);
+
+ pass = _B_TRUE;
+
+ if (debug)
+ printf("Receiving: controllen=%u, \n", msg.msg_controllen);
+
+ nbytes = recvmsg(sock, &msg, 0);
+
+ if (nbytes == -1) {
+ pass = _B_FALSE;
+ fprintf(stderr, "recvmsg() failed: %s\n", strerror(errno));
+ goto out;
+ }
+
+ if (debug) {
+ printf("Received: controllen=%u, flags=%#x\n",
+ msg.msg_controllen, msg.msg_flags);
+ }
+
+ check(msg.msg_flags, t->x_flags, "msg_flags");
+ check(msg.msg_controllen, t->x_controllen, "msg_controllen");
+
+ for (cm = CMSG_FIRSTHDR(&msg); cm; cm = CMSG_NXTHDR(&msg, cm)) {
+ void *data, *end;
+
+ if (debug) {
+ printf(" >> : Got cmsg %x/%x - %u\n", cm->cmsg_level,
+ cm->cmsg_type, cm->cmsg_len);
+ }
+
+ if (cm->cmsg_type != SCM_RIGHTS) {
+ if (debug)
+ printf(" : skipping cmsg\n");
+ continue;
+ }
+
+ check(cm->cmsg_len - CMSG_LEN(0),
+ t->x_cmsg_datalen, "cmsg_len");
+
+ /* Close any received file descriptors */
+ data = CMSG_DATA(cm);
+
+ if ((msg.msg_flags & MSG_CTRUNC) &&
+ CMSG_NXTHDR(&msg, cm) == NULL) {
+ /*
+ * illumos did not previously adjust cmsg_len on
+ * truncation. This is the last cmsg, derive the
+ * length from msg_controllen
+ */
+ end = msg.msg_control + msg.msg_controllen;
+ } else {
+ end = data + cm->cmsg_len - CMSG_LEN(0);
+ }
+
+ while (data <= end - sizeof (int)) {
+ int *a = (int *)data;
+ if (debug)
+ printf(" : close(%d)\n", *a);
+ if (close(*a) == -1) {
+ pass = _B_FALSE;
+ fprintf(stderr, " !!!: "
+ "failed to close fd %d - %s\n", *a,
+ strerror(errno));
+ }
+ data += sizeof (int);
+ }
+ }
+
+out:
+
+ check_fds("client");
+ check(fdcount, 0, "client descriptors");
+ printf(" + : %s %s\n", pass ? "PASS" : "FAIL", t->name);
+
+ return (pass);
+}
+
+static int
+client(const char *sockpath, pid_t pid)
+{
+ struct sockaddr_un addr;
+ sigset_t set;
+ cmsg_test_t *t;
+ int ret = 0;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR1);
+ sigaddset(&set, SIGINT);
+
+ send_and_wait(pid, &set, 0, SIGUSR1);
+
+ sock = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (sock == -1)
+ err(EXIT_FAILURE, "failed to create socket");
+ addr.sun_family = AF_UNIX;
+ strlcpy(addr.sun_path, sockpath, sizeof (addr.sun_path));
+ if (connect(sock, (struct sockaddr *)&addr, sizeof (addr)) == -1)
+ err(EXIT_FAILURE, "could not connect to server socket");
+
+ for (t = tests; t->name != NULL; t++) {
+ send_and_wait(pid, &set, SIGUSR2, SIGUSR1);
+ if (!recvtest(t))
+ ret = 1;
+ }
+
+ close(sock);
+
+ return (ret);
+}
+
+int
+main(int argc, const char **argv)
+{
+ char sockpath[] = "/tmp/cmsg.testsock.XXXXXX";
+ pid_t pid, ppid;
+ sigset_t set;
+ int ret = 0;
+
+ if (argc > 1 && strcmp(argv[1], "-d") == 0)
+ debug = _B_TRUE;
+
+ sigfillset(&set);
+ sigdelset(&set, SIGINT);
+ sigdelset(&set, SIGTSTP);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+
+ if (mktemp(sockpath) == NULL)
+ err(EXIT_FAILURE, "Failed to make temporary socket path");
+
+ ppid = getpid();
+ pid = fork();
+ switch (pid) {
+ case -1:
+ err(EXIT_FAILURE, "fork failed");
+ case 0:
+ return (server(sockpath, ppid));
+ default:
+ break;
+ }
+
+ ret = client(sockpath, pid);
+ kill(pid, SIGINT);
+
+ unlink(sockpath);
+
+ return (ret);
+}
diff --git a/usr/src/uts/common/fs/sockfs/socksubr.c b/usr/src/uts/common/fs/sockfs/socksubr.c
index 2c010343bb..2a03f0073d 100644
--- a/usr/src/uts/common/fs/sockfs/socksubr.c
+++ b/usr/src/uts/common/fs/sockfs/socksubr.c
@@ -23,8 +23,8 @@
* Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015, Joyent, Inc. All rights reserved.
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
- * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
* Copyright 2015, Joyent, Inc. All rights reserved.
+ * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
*/
#include <sys/types.h>
@@ -962,7 +962,46 @@ so_closefds(void *control, t_uscalar_t controllen, int oldflg,
(int)CMSG_CONTENTLEN(cmsg),
startoff - (int)sizeof (struct cmsghdr));
}
- startoff -= cmsg->cmsg_len;
+ startoff -= ROUNDUP_cmsglen(cmsg->cmsg_len);
+ }
+}
+
+/*
+ * Handle truncation of a cmsg when the receive buffer is not big enough.
+ * Adjust the cmsg_len header field in the last cmsg that will be included in
+ * the buffer to reflect the number of bytes included.
+ */
+void
+so_truncatecmsg(void *control, t_uscalar_t controllen, uint_t maxlen)
+{
+ struct cmsghdr *cmsg;
+ uint_t len = 0;
+
+ if (control == NULL)
+ return;
+
+ for (cmsg = control;
+ CMSG_VALID(cmsg, control, (uintptr_t)control + controllen);
+ cmsg = CMSG_NEXT(cmsg)) {
+
+ len += ROUNDUP_cmsglen(cmsg->cmsg_len);
+
+ if (len > maxlen) {
+ /*
+ * This cmsg is the last one that will be included in
+ * the truncated buffer.
+ */
+ socklen_t diff = len - maxlen;
+
+ if (diff < CMSG_CONTENTLEN(cmsg)) {
+ dprint(1, ("so_truncatecmsg: %d -> %d\n",
+ cmsg->cmsg_len, cmsg->cmsg_len - diff));
+ cmsg->cmsg_len -= diff;
+ } else {
+ cmsg->cmsg_len = sizeof (struct cmsghdr);
+ }
+ break;
+ }
}
}
diff --git a/usr/src/uts/common/fs/sockfs/socksyscalls.c b/usr/src/uts/common/fs/sockfs/socksyscalls.c
index 6a049b1828..30666f73ca 100644
--- a/usr/src/uts/common/fs/sockfs/socksyscalls.c
+++ b/usr/src/uts/common/fs/sockfs/socksyscalls.c
@@ -24,6 +24,7 @@
* Copyright 2015, Joyent, Inc. All rights reserved.
* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
*/
#include <sys/types.h>
@@ -831,7 +832,7 @@ recvit(int sock, struct nmsghdr *msg, struct uio *uiop, int flags,
void *name;
socklen_t namelen;
void *control;
- socklen_t controllen;
+ socklen_t controllen, free_controllen;
ssize_t len;
int error;
@@ -858,6 +859,8 @@ recvit(int sock, struct nmsghdr *msg, struct uio *uiop, int flags,
lwp_stat_update(LWP_STAT_MSGRCV, 1);
releasef(sock);
+ free_controllen = msg->msg_controllen;
+
error = copyout_name(name, namelen, namelenp,
msg->msg_name, msg->msg_namelen);
if (error)
@@ -887,11 +890,7 @@ recvit(int sock, struct nmsghdr *msg, struct uio *uiop, int flags,
goto err;
}
}
- /*
- * Note: This MUST be done last. There can be no "goto err" after this
- * point since it could make so_closefds run twice on some part
- * of the file descriptor array.
- */
+
if (controllen != 0) {
if (!(flags & MSG_XPG4_2)) {
/*
@@ -900,36 +899,65 @@ recvit(int sock, struct nmsghdr *msg, struct uio *uiop, int flags,
*/
controllen &= ~((int)sizeof (uint32_t) - 1);
}
+
+ if (msg->msg_controllen > controllen || control == NULL) {
+ /*
+ * If the truncated part contains file descriptors,
+ * then they must be closed in the kernel as they
+ * will not be included in the data returned to
+ * user space. Close them now so that the header size
+ * can be safely adjusted prior to copyout. In case of
+ * an error during copyout, the remaining file
+ * descriptors will be closed in the error handler
+ * below.
+ */
+ so_closefds(msg->msg_control, msg->msg_controllen,
+ !(flags & MSG_XPG4_2),
+ control == NULL ? 0 : controllen);
+
+ /*
+ * In the case of a truncated control message, the last
+ * cmsg header that fits into the available buffer
+ * space must be adjusted to reflect the actual amount
+ * of associated data that will be returned. This only
+ * needs to be done for XPG4 messages as non-XPG4
+ * messages are not structured (they are just a
+ * buffer and a length - msg_accrights(len)).
+ */
+ if (control != NULL && (flags & MSG_XPG4_2)) {
+ so_truncatecmsg(msg->msg_control,
+ msg->msg_controllen, controllen);
+ msg->msg_controllen = controllen;
+ }
+ }
+
error = copyout_arg(control, controllen, controllenp,
msg->msg_control, msg->msg_controllen);
+
if (error)
goto err;
- if (msg->msg_controllen > controllen || control == NULL) {
- if (control == NULL)
- controllen = 0;
- so_closefds(msg->msg_control, msg->msg_controllen,
- !(flags & MSG_XPG4_2), controllen);
- }
}
if (msg->msg_namelen != 0)
kmem_free(msg->msg_name, (size_t)msg->msg_namelen);
- if (msg->msg_controllen != 0)
- kmem_free(msg->msg_control, (size_t)msg->msg_controllen);
+ if (free_controllen != 0)
+ kmem_free(msg->msg_control, (size_t)free_controllen);
return (len - uiop->uio_resid);
err:
/*
* If we fail and the control part contains file descriptors
- * we have to close the fd's.
+ * we have to close them. For a truncated control message, the
+ * descriptors which were cut off have already been closed and the
+ * length adjusted so that they will not be closed again.
*/
if (msg->msg_controllen != 0)
so_closefds(msg->msg_control, msg->msg_controllen,
!(flags & MSG_XPG4_2), 0);
if (msg->msg_namelen != 0)
kmem_free(msg->msg_name, (size_t)msg->msg_namelen);
- if (msg->msg_controllen != 0)
- kmem_free(msg->msg_control, (size_t)msg->msg_controllen);
+ if (free_controllen != 0)
+ kmem_free(msg->msg_control, (size_t)free_controllen);
return (set_errno(error));
}
diff --git a/usr/src/uts/common/sys/socketvar.h b/usr/src/uts/common/sys/socketvar.h
index 55a182fa68..910f2a839a 100644
--- a/usr/src/uts/common/sys/socketvar.h
+++ b/usr/src/uts/common/sys/socketvar.h
@@ -38,7 +38,7 @@
*/
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
- * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
+ * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
*/
#ifndef _SYS_SOCKETVAR_H
@@ -930,6 +930,8 @@ extern void fdbuf_free(struct fdbuf *);
extern mblk_t *fdbuf_allocmsg(int, struct fdbuf *);
extern int fdbuf_create(void *, int, struct fdbuf **);
extern void so_closefds(void *, t_uscalar_t, int, int);
+extern void so_truncatecmsg(void *, t_uscalar_t, uint_t);
+
extern int so_getfdopt(void *, t_uscalar_t, int, void **, int *);
t_uscalar_t so_optlen(void *, t_uscalar_t, int);
extern void so_cmsg2opt(void *, t_uscalar_t, int, mblk_t *);