chiark
/
gitweb
/
~mdw
/
checkpath
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
checkpath.c: Allocate the state from a resource pool.
[checkpath]
/
checkpath.c
diff --git
a/checkpath.c
b/checkpath.c
index 9c1508645e02933188401026947284dbaa064be2..95524ae24f34c3b9fc01d670c9c1585cd029b32a 100644
(file)
--- a/
checkpath.c
+++ b/
checkpath.c
@@
-44,6
+44,7
@@
#include <mLib/alloc.h>
#include <mLib/dstr.h>
#include <mLib/macros.h>
#include <mLib/alloc.h>
#include <mLib/dstr.h>
#include <mLib/macros.h>
+#include <mLib/pool.h>
#include "checkpath.h"
#include "checkpath.h"
@@
-63,12
+64,15
@@
struct elt {
char e_name[1]; /* Name of the directory */
};
char e_name[1]; /* Name of the directory */
};
+struct state {
+ pool *p; /* Allocation pool */
+ struct elt *sp; /* Stack pointer for list */
+ dstr path; /* Current path string */
+};
/*----- Static variables --------------------------------------------------*/
static const struct elt rootnode = { 0, 0, 0 }; /* Root of the list */
/*----- Static variables --------------------------------------------------*/
static const struct elt rootnode = { 0, 0, 0 }; /* Root of the list */
-static struct elt *sp; /* Stack pointer for list */
-static dstr d = DSTR_INIT; /* Current path string */
/*----- Main code ---------------------------------------------------------*/
/*----- Main code ---------------------------------------------------------*/
@@
-87,9
+91,9
@@
static dstr d = DSTR_INIT; /* Current path string */
static struct elt *splitpath(const char *path, struct elt *tail)
{
struct elt *head, **ee = &head, *e;
static struct elt *splitpath(const char *path, struct elt *tail)
{
struct elt *head, **ee = &head, *e;
+ size_t n;
while (*path) {
while (*path) {
- size_t n;
/* --- Either a leading `/', or a doubled one --- *
*
/* --- Either a leading `/', or a doubled one --- *
*
@@
-124,56
+128,59
@@
static struct elt *splitpath(const char *path, struct elt *tail)
/* --- @pop@ --- *
*
/* --- @pop@ --- *
*
- * Arguments:
---
+ * Arguments:
@struct state *state@ = working state
*
* Returns: ---
*
* Use: Removes the top item from the directory stack.
*/
*
* Returns: ---
*
* Use: Removes the top item from the directory stack.
*/
-static void pop(
void
)
+static void pop(
struct state *state
)
{
{
+ struct elt *sp = state->sp, *e;
+
if (sp->e_link) {
if (sp->e_link) {
-
struct elt *
e = sp->e_link;
-
d
.len = sp->e_offset;
- DPUTZ(&
d
);
- xfree(s
p);
sp = e;
+ e = sp->e_link;
+
state->path
.len = sp->e_offset;
+ DPUTZ(&
state->path
);
+ xfree(s
tate->sp); state->
sp = e;
}
}
/* --- @popall@ --- *
*
}
}
/* --- @popall@ --- *
*
- * Arguments:
---
+ * Arguments:
@struct state *state@ = working state
*
* Returns: ---
*
* Use: Removes all the items from the directory stack.
*/
*
* Returns: ---
*
* Use: Removes all the items from the directory stack.
*/
-static void popall(
void
)
- { while (s
p->e_link) pop(
); }
+static void popall(
struct state *state
)
+ { while (s
tate->sp->e_link) pop(state
); }
/* --- @push@ --- *
*
/* --- @push@ --- *
*
- * Arguments: @struct elt *e@ = pointer to directory element
+ * Arguments: @struct state *state@ = working state
+ * @struct elt *e@ = pointer to directory element
*
* Returns: ---
*
* Use: Pushes a new subdirectory onto the stack.
*/
*
* Returns: ---
*
* Use: Pushes a new subdirectory onto the stack.
*/
-static void push(struct elt *e)
+static void push(struct
state *state, struct
elt *e)
{
{
- e->e_link = sp;
- e->e_offset =
d
.len;
- DPUTC(&
d
, '/');
- DPUTS(&
d
, e->e_name);
- sp = e;
+ e->e_link = s
tate->s
p;
+ e->e_offset =
state->path
.len;
+ DPUTC(&
state->path
, '/');
+ DPUTS(&
state->path
, e->e_name);
+ s
tate->s
p = e;
}
/* --- @report@ --- *
*
}
/* --- @report@ --- *
*
- * Arguments: @const struct checkpath *cp@ = pointer to
context
+ * Arguments: @const struct checkpath *cp@ = pointer to
query
* @unsigned what@ = what sort of report is this?
* @int verbose@ = how verbose is this?
* @const char *p@ = what path does it refer to?
* @unsigned what@ = what sort of report is this?
* @int verbose@ = how verbose is this?
* @const char *p@ = what path does it refer to?
@@
-269,7
+276,7
@@
static void report(const struct checkpath *cp, unsigned what, int verbose,
*
* Arguments: @const char *p@ = name of directory to check
* @struct stat *st@ = pointer to @stat@(2) block for it
*
* Arguments: @const char *p@ = name of directory to check
* @struct stat *st@ = pointer to @stat@(2) block for it
- * @const struct checkpath *cp@ = pointer to
caller parameters
+ * @const struct checkpath *cp@ = pointer to
query
* @unsigned f@ = various flags (@SF_...@)
*
* Returns: Zero if everything's OK, else bitmask of problems.
* @unsigned f@ = various flags (@SF_...@)
*
* Returns: Zero if everything's OK, else bitmask of problems.
@@
-291,12
+298,12
@@
static unsigned sanity(const char *p, struct stat *st,
if (S_ISDIR(st->st_mode) &&
(!(f & SF_LAST) || (cp->cp_what & CP_STICKYOK)))
if (S_ISDIR(st->st_mode) &&
(!(f & SF_LAST) || (cp->cp_what & CP_STICKYOK)))
- stickyok =
01000
;
+ stickyok =
S_ISVTX
;
/* --- Check for world-writability --- */
if ((cp->cp_what & CP_WRWORLD) &&
/* --- Check for world-writability --- */
if ((cp->cp_what & CP_WRWORLD) &&
- (st->st_mode & (
0002 | stickyok)) == 0002
) {
+ (st->st_mode & (
S_IWOTH | stickyok)) == S_IWOTH
) {
bad |= CP_WRWORLD;
report(cp, CP_WRWORLD, 1, p, "** world writable **");
}
bad |= CP_WRWORLD;
report(cp, CP_WRWORLD, 1, p, "** world writable **");
}
@@
-304,7
+311,7
@@
static unsigned sanity(const char *p, struct stat *st,
/* --- Check for group-writability --- */
if ((cp->cp_what & (CP_WRGRP | CP_WROTHGRP)) &&
/* --- Check for group-writability --- */
if ((cp->cp_what & (CP_WRGRP | CP_WROTHGRP)) &&
- (st->st_mode & (
0020 | stickyok)) == 0020
) {
+ (st->st_mode & (
S_IWGRP | stickyok)) == S_IWGRP
) {
b = CP_WRGRP;
if (cp->cp_what & CP_WROTHGRP) {
b = CP_WRGRP;
if (cp->cp_what & CP_WROTHGRP) {
@@
-350,13
+357,20
@@
unsigned checkpath(const char *p, const struct checkpath *cp)
{
char cwd[PATH_MAX];
struct elt *e, *ee;
{
char cwd[PATH_MAX];
struct elt *e, *ee;
+ struct state *state;
+ pool *pp;
struct stat st;
unsigned bad = 0;
struct stat st;
unsigned bad = 0;
+ dstr buf = DSTR_INIT;
+ int i;
- /* --- Initialize
stack pointer and path string
--- */
+ /* --- Initialize
the state
--- */
- sp = (/*unconst*/ struct elt *)&rootnode;
- dstr_destroy(&d);
+ pp = pool_create(arena_global);
+ state = pool_alloc(pp, sizeof(*state));
+ state->p = pp;
+ state->sp = (/*unconst*/ struct elt *)&rootnode;
+ dstr_create(&state->path);
/* --- Try to find the current directory --- */
/* --- Try to find the current directory --- */
@@
-397,7
+411,7
@@
unsigned checkpath(const char *p, const struct checkpath *cp)
/* --- Backtrack on `..' elements --- */
else if (strcmp(ee->e_name, "..") == 0) {
/* --- Backtrack on `..' elements --- */
else if (strcmp(ee->e_name, "..") == 0) {
- pop();
+ pop(
state
);
xfree(ee);
ee = e;
continue;
xfree(ee);
ee = e;
continue;
@@
-405,13
+419,13
@@
unsigned checkpath(const char *p, const struct checkpath *cp)
/* --- Everything else gets pushed on the end --- */
/* --- Everything else gets pushed on the end --- */
- push(ee);
+ push(
state,
ee);
ee = e;
/* --- Find out what sort of a thing this is --- */
ee = e;
/* --- Find out what sort of a thing this is --- */
- if (lstat(
d
.buf, &st)) {
- report(cp, CP_ERROR, 0,
d
.buf, "can't stat: %e");
+ if (lstat(
state->path
.buf, &st)) {
+ report(cp, CP_ERROR, 0,
state->path
.buf, "can't stat: %e");
bad |= CP_ERROR;
break;
}
bad |= CP_ERROR;
break;
}
@@
-419,19
+433,18
@@
unsigned checkpath(const char *p, const struct checkpath *cp)
/* --- Handle symbolic links specially --- */
if (S_ISLNK(st.st_mode)) {
/* --- Handle symbolic links specially --- */
if (S_ISLNK(st.st_mode)) {
- dstr buf = DSTR_INIT;
- int i;
/* --- Resolve the link --- */
/* --- Resolve the link --- */
+ dstr_reset(&buf);
dstr_ensure(&buf, st.st_size + 1);
dstr_ensure(&buf, st.st_size + 1);
- if ((i = readlink(
d
.buf, buf.buf, buf.sz)) < 0) {
- report(cp, CP_ERROR, 0,
d
.buf, "can't readlink: %e");
+ if ((i = readlink(
state->path
.buf, buf.buf, buf.sz)) < 0) {
+ report(cp, CP_ERROR, 0,
state->path
.buf, "can't readlink: %e");
bad |= CP_ERROR;
break;
}
buf.buf[i] = 0;
bad |= CP_ERROR;
break;
}
buf.buf[i] = 0;
- report(cp, CP_SYMLINK, 2,
d
.buf, "symlink -> `%s'", buf.buf);
+ report(cp, CP_SYMLINK, 2,
state->path
.buf, "symlink -> `%s'", buf.buf);
/* --- Handle sticky parents --- *
*
/* --- Handle sticky parents --- *
*
@@
-441,32
+454,31
@@
unsigned checkpath(const char *p, const struct checkpath *cp)
*/
if ((cp->cp_what & CP_WROTHUSR) &&
*/
if ((cp->cp_what & CP_WROTHUSR) &&
- (sp->e_link->e_flags & EF_STICKY) &&
+ (s
tate->s
p->e_link->e_flags & EF_STICKY) &&
st.st_uid != cp->cp_uid && st.st_uid != 0) {
bad |= CP_WROTHUSR;
st.st_uid != cp->cp_uid && st.st_uid != 0) {
bad |= CP_WROTHUSR;
- report(cp, CP_WROTHUSR, 1,
d
.buf,
+ report(cp, CP_WROTHUSR, 1,
state->path
.buf,
"symlink modifiable by user %u", st.st_uid);
}
/* --- Sort out what to do from here --- */
if (buf.buf[0] == '/')
"symlink modifiable by user %u", st.st_uid);
}
/* --- Sort out what to do from here --- */
if (buf.buf[0] == '/')
- popall();
+ popall(
state
);
else
else
- pop();
+ pop(
state
);
ee = splitpath(buf.buf, ee);
ee = splitpath(buf.buf, ee);
- dstr_destroy(&buf);
continue;
}
/* --- Run the sanity check on this path element --- */
continue;
}
/* --- Run the sanity check on this path element --- */
- bad |= sanity(
d
.buf, &st, cp, ee ? 0 : SF_LAST);
+ bad |= sanity(
state->path
.buf, &st, cp, ee ? 0 : SF_LAST);
if (S_ISDIR(st.st_mode)) {
if (S_ISDIR(st.st_mode)) {
- if (st.st_mode &
01000
)
- sp->e_flags |= EF_STICKY;
- report(cp, CP_REPORT, 4,
d
.buf, "directory");
+ if (st.st_mode &
S_ISVTX
)
+ s
tate->s
p->e_flags |= EF_STICKY;
+ report(cp, CP_REPORT, 4,
state->path
.buf, "directory");
continue;
}
continue;
}
@@
-487,7
+499,10
@@
unsigned checkpath(const char *p, const struct checkpath *cp)
}
}
}
}
- popall();
+ popall(state);
+ dstr_destroy(&state->path);
+ dstr_destroy(&buf);
+ pool_destroy(state->p);
return (bad);
}
return (bad);
}