summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/modload/drvsubr.c87
1 files changed, 66 insertions, 21 deletions
diff --git a/usr/src/cmd/modload/drvsubr.c b/usr/src/cmd/modload/drvsubr.c
index 9e78f8abae..d04d914e14 100644
--- a/usr/src/cmd/modload/drvsubr.c
+++ b/usr/src/cmd/modload/drvsubr.c
@@ -187,6 +187,44 @@ append_to_file(
return (NOERR);
}
+/*
+ * Require exact match to delete a driver alias/permission entry.
+ * Note line argument does not remain unchanged. Return 1 if matched.
+ */
+static int
+match_entry(char *line, char *match)
+{
+ char *token, *p;
+ int n;
+
+ /* skip any leading white space */
+ while (*line && ((*line == ' ') || (*line == '\t')))
+ line++;
+ /*
+ * Find separator for driver name, either space or colon
+ * minor_perm: <driver>:<perm>
+ * driver_aliases: <driver> <alias>
+ * extra_privs: <driver>:<priv>
+ */
+ if ((token = strpbrk(line, " :\t")) == NULL)
+ return (0);
+ token++;
+ /* skip leading white space and quotes */
+ while (*token && (*token == ' ' || *token == '\t' ||
+ *token == '"' || *token == '\''))
+ token++;
+ /* strip trailing newline, white space and quotes */
+ n = strlen(token);
+ p = token + n-1;
+ while (n > 0 && (*p == '\n' || *p == ' ' || *p == '\t' ||
+ *p == '"' || *p == '\'')) {
+ *p-- = 0;
+ n--;
+ }
+ if (n == 0)
+ return (0);
+ return (strcmp(token, match) == 0);
+}
/*
* open file
@@ -214,16 +252,14 @@ delete_entry(
int status = NOERR;
int drvr_found = 0;
boolean_t nomatch = B_TRUE;
- char *newfile, *tptr, *cp, *dup;
+ char *newfile, *tptr, *cp;
char line[MAX_DBFILE_ENTRY], drv[FILENAME_MAX + 1];
FILE *fp, *newfp;
struct group *sysgrp;
+ char *copy; /* same size as line */
/*
* check if match is specified and if it equals " "
- * this is a special case handling as we do a strstr(3STRING)
- * to match an entry. By default all entries are space separated
- * and without this check all entries of the file could get deleted.
*/
if (match && (*match == ' ' && strlen(match) == 1)) {
(void) fprintf(stderr, gettext(ERR_INT_UPDATE), oldfile);
@@ -236,13 +272,15 @@ delete_entry(
return (ERROR);
}
- /*
- * Build filename for temporary file
- */
+ /* Space for defensive copy of input line */
+ copy = calloc(sizeof (line), 1);
- if ((tptr = calloc(strlen(oldfile) + strlen(XEND) + 1, 1)) == NULL) {
+ /* Build filename for temporary file */
+ tptr = calloc(strlen(oldfile) + strlen(XEND) + 1, 1);
+ if (tptr == NULL || copy == NULL) {
perror(NULL);
(void) fprintf(stderr, gettext(ERR_NO_MEM));
+ return (ERROR);
}
(void) strcpy(tptr, oldfile);
@@ -267,36 +305,32 @@ delete_entry(
}
while ((fgets(line, sizeof (line), fp) != NULL) && status == NOERR) {
- /* copy the whole line into dup */
- if ((dup = strdup(line)) == NULL) {
- perror(NULL);
- (void) fprintf(stderr, gettext(ERR_NO_MEM));
+ /* copy the whole line */
+ if (strlcpy(copy, line, sizeof (line)) >= sizeof (line)) {
+ (void) fprintf(stderr, gettext(ERR_UPDATE), oldfile);
status = ERROR;
break;
}
/* cut off comments starting with '#' */
- if ((cp = strchr(dup, '#')) != NULL)
+ if ((cp = strchr(copy, '#')) != NULL)
*cp = '\0';
/* ignore comment or blank lines */
- if (is_blank(dup)) {
+ if (is_blank(copy)) {
if (fputs(line, newfp) == EOF) {
(void) fprintf(stderr, gettext(ERR_UPDATE),
oldfile);
status = ERROR;
}
- free(dup);
continue;
}
/* get the driver name */
- if (sscanf(dup, "%s", drv) != 1) {
+ if (sscanf(copy, "%s", drv) != 1) {
(void) fprintf(stderr, gettext(ERR_BAD_LINE),
oldfile, line);
status = ERROR;
- free(dup);
break;
}
- free(dup);
for (i = strcspn(drv, marker); i < FILENAME_MAX; i++) {
drv[i] = '\0';
@@ -315,7 +349,17 @@ delete_entry(
if ((strcmp(oldfile, minor_perm) == 0) ||
(strcmp(oldfile, extra_privs) == 0) ||
(strcmp(oldfile, driver_aliases) == 0)) {
- if (strstr(line, match)) {
+
+ /* make defensive copy */
+ if (strlcpy(copy, line, sizeof (line))
+ >= sizeof (line)) {
+ (void) fprintf(stderr,
+ gettext(ERR_UPDATE),
+ oldfile);
+ status = ERROR;
+ break;
+ }
+ if (match_entry(copy, match)) {
nomatch = B_FALSE;
} else {
if ((fputs(line, newfp)) ==
@@ -335,6 +379,8 @@ delete_entry(
} /* end of while */
(void) fclose(fp);
+ free(tptr);
+ free(copy);
/* Make sure that the file is on disk */
if (fflush(newfp) != 0 || fsync(fileno(newfp)) != 0)
@@ -1059,8 +1105,7 @@ load_driver(char *driver_name, int verbose_flag)
if (exec_status != NOERR) {
/* no clean : name and major number are bound */
- (void) fprintf(stderr, gettext(ERR_CONFIG),
- driver_name);
+ (void) fprintf(stderr, gettext(ERR_CONFIG), driver_name);
}
}