From 6e202c432e2f16dfa83a7dc21b759c03623fa394 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 11:33:22 +0000 Subject: Detect asprintf's ENOMEM in procfs.c rather than everywhere * procfs.h: Make CONTENTS_LEN an ssize_t rather than a size_t, and document the change. * procfs.c (procfs_get_contents): Initialize CONTENTS_LEN to a negative value, and fail with ENOMEM if it's still negative after the callback returns. (everywhere): Update to ssize_t. * dircat.c, netfs.c, process.c, procfs_dir.c, proclist.c, rootdir.c: Update to ssize_t and the new GET_CONTENTS semantics. --- dircat.c | 4 ++-- netfs.c | 8 ++++---- process.c | 54 ++++++++++++++++++++---------------------------------- procfs.c | 13 ++++++++----- procfs.h | 14 ++++++++------ procfs_dir.c | 2 +- proclist.c | 2 +- rootdir.c | 30 +++++++++++++++--------------- 8 files changed, 59 insertions(+), 68 deletions(-) diff --git a/dircat.c b/dircat.c index 93bb2fe..bb66508 100644 --- a/dircat.c +++ b/dircat.c @@ -8,7 +8,7 @@ struct dircat_node }; static error_t -dircat_get_contents (void *hook, char **contents, size_t *contents_len) +dircat_get_contents (void *hook, char **contents, ssize_t *contents_len) { struct dircat_node *dcn = hook; int i, sz, pos; @@ -20,7 +20,7 @@ dircat_get_contents (void *hook, char **contents, size_t *contents_len) for (i=0; dcn->dirs[i]; i++) { char *subcon; - size_t sublen; + ssize_t sublen; err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); if (err) diff --git a/netfs.c b/netfs.c index 6fd82a0..e41e062 100644 --- a/netfs.c +++ b/netfs.c @@ -30,7 +30,7 @@ int netfs_maxsymlinks = PROCFS_MAXSYMLINKS; error_t netfs_validate_stat (struct node *np, struct iouser *cred) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; /* Only symlinks need to have their size filled, before a read is @@ -54,7 +54,7 @@ error_t netfs_attempt_read (struct iouser *cred, struct node *np, loff_t offset, size_t *len, void *data) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; err = procfs_get_contents (np, &contents, &contents_len); @@ -79,7 +79,7 @@ error_t netfs_attempt_readlink (struct iouser *user, struct node *np, char *buf) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; err = procfs_get_contents (np, &contents, &contents_len); @@ -137,7 +137,7 @@ error_t netfs_get_dirents (struct iouser *cred, struct node *dir, vm_size_t bufsize, int *amt) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; err = procfs_get_contents (dir, &contents, &contents_len); diff --git a/process.c b/process.c index fa79552..624f79e 100644 --- a/process.c +++ b/process.c @@ -12,18 +12,18 @@ /* Implementations for the process_file_desc.get_contents callback. */ -static char * -process_file_gc_cmdline (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_cmdline (struct proc_stat *ps, char **contents) { - *len = proc_stat_args_len(ps); - return proc_stat_args(ps); + *contents = proc_stat_args(ps); + return proc_stat_args_len(ps); } -static char * -process_file_gc_environ (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_environ (struct proc_stat *ps, char **contents) { - *len = proc_stat_args_len(ps); - return proc_stat_args(ps); + *contents = proc_stat_env(ps); + return proc_stat_env_len(ps); } static char state_char (struct proc_stat *ps) @@ -71,17 +71,16 @@ static long long int jiff_tv (time_value_t tv) return usecs * 100 / 1000000; } -static char * -process_file_gc_stat (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_stat (struct proc_stat *ps, char **contents) { struct procinfo *pi = proc_stat_proc_info (ps); task_basic_info_t tbi = proc_stat_task_basic_info (ps); thread_basic_info_t thbi = proc_stat_thread_basic_info (ps); - char *contents; /* See proc(5) for more information about the contents of each field for the Linux procfs. */ - *len = asprintf (&contents, + return asprintf (contents, "%d (%s) %c " /* pid, command, state */ "%d %d %d " /* ppid, pgid, session */ "%d %d " /* controling tty stuff */ @@ -122,31 +121,23 @@ process_file_gc_stat (struct proc_stat *ps, size_t *len) 0, 0, 0, 0LL); - - return len >= 0 ? contents : NULL; } -static char * -process_file_gc_statm (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_statm (struct proc_stat *ps, char **contents) { task_basic_info_t tbi = proc_stat_task_basic_info (ps); - char *contents; - - *len = asprintf (&contents, + return asprintf (contents, "%lu %lu 0 0 0 0 0\n", tbi->virtual_size / sysconf(_SC_PAGE_SIZE), tbi->resident_size / sysconf(_SC_PAGE_SIZE)); - - return len >= 0 ? contents : NULL; } -static char * -process_file_gc_status (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_status (struct proc_stat *ps, char **contents) { task_basic_info_t tbi = proc_stat_task_basic_info (ps); - char *contents; - - *len = asprintf (&contents, + return asprintf (contents, "Name:\t%s\n" "State:\t%s\n" "Tgid:\t%u\n" @@ -172,8 +163,6 @@ process_file_gc_status (struct proc_stat *ps, size_t *len) tbi->resident_size / 1024, tbi->resident_size / 1024, proc_stat_num_threads (ps)); - - return len >= 0 ? contents : NULL; } @@ -186,7 +175,7 @@ struct process_file_desc /* Once we have acquired the necessary information, there can be only memory allocation errors, hence this simplified signature. */ - char *(*get_contents) (struct proc_stat *ps, size_t *len); + ssize_t (*get_contents) (struct proc_stat *ps, char **contents); /* The cmdline and environ contents don't need any cleaning since they are part of a proc_stat structure. */ @@ -204,7 +193,7 @@ struct process_file_node }; static error_t -process_file_get_contents (void *hook, char **contents, size_t *contents_len) +process_file_get_contents (void *hook, char **contents, ssize_t *contents_len) { struct process_file_node *file = hook; error_t err; @@ -215,10 +204,7 @@ process_file_get_contents (void *hook, char **contents, size_t *contents_len) if ((proc_stat_flags (file->ps) & file->desc->needs) != file->desc->needs) return EIO; - *contents = file->desc->get_contents (file->ps, contents_len); - if (! *contents) - return ENOMEM; - + *contents_len = file->desc->get_contents (file->ps, contents); return 0; } diff --git a/procfs.c b/procfs.c index a5f52b5..6d15e4f 100644 --- a/procfs.c +++ b/procfs.c @@ -13,20 +13,20 @@ struct netnode /* (cached) contents of the node */ char *contents; - size_t contents_len; + ssize_t contents_len; /* parent directory, if applicable */ struct node *parent; }; void -procfs_cleanup_contents_with_free (void *hook, char *cont, size_t len) +procfs_cleanup_contents_with_free (void *hook, char *cont, ssize_t len) { free (cont); } void -procfs_cleanup_contents_with_vm_deallocate (void *hook, char *cont, size_t len) +procfs_cleanup_contents_with_vm_deallocate (void *hook, char *cont, ssize_t len) { vm_deallocate (mach_task_self (), (vm_address_t) cont, (vm_size_t) len); } @@ -109,7 +109,7 @@ procfs_make_ino (struct node *np, const char *filename) return (unsigned long) jrand48 (x); } -error_t procfs_get_contents (struct node *np, char **data, size_t *data_len) +error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len) { if (np->nn->ops->enable_refresh_hack_and_break_readdir && np->nn->contents) { @@ -122,12 +122,15 @@ error_t procfs_get_contents (struct node *np, char **data, size_t *data_len) if (! np->nn->contents && np->nn->ops->get_contents) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; + contents_len = -1; err = np->nn->ops->get_contents (np->nn->hook, &contents, &contents_len); if (err) return err; + if (contents_len < 0) + return ENOMEM; np->nn->contents = contents; np->nn->contents_len = contents_len; diff --git a/procfs.h b/procfs.h index 8336ee8..e8ef18b 100644 --- a/procfs.h +++ b/procfs.h @@ -16,9 +16,11 @@ struct procfs_node_ops symlink or directory, as determined by the file mode in netnode->nn_stat. For regular files and symlinks, they are what you would expect; for directories, they are an argz vector of the - names of the entries. */ - error_t (*get_contents) (void *hook, char **contents, size_t *contents_len); - void (*cleanup_contents) (void *hook, char *contents, size_t contents_len); + names of the entries. If upon return, *CONTENTS_LEN is negative or + unchanged, the call is considered to have failed because of a memory + allocation error. */ + error_t (*get_contents) (void *hook, char **contents, ssize_t *contents_len); + void (*cleanup_contents) (void *hook, char *contents, ssize_t contents_len); /* Lookup NAME in this directory, and store the result in *np. The returned node should be created by lookup() using procfs_make_node() @@ -41,8 +43,8 @@ struct procfs_node_ops }; /* These helper functions can be used as procfs_node_ops.cleanup_contents. */ -void procfs_cleanup_contents_with_free (void *, char *, size_t); -void procfs_cleanup_contents_with_vm_deallocate (void *, char *, size_t); +void procfs_cleanup_contents_with_free (void *, char *, ssize_t); +void procfs_cleanup_contents_with_vm_deallocate (void *, char *, ssize_t); /* Create a new node and return it. Returns NULL if it fails to allocate enough memory. In this case, ops->cleanup will be invoked. */ @@ -69,7 +71,7 @@ void procfs_node_chtype (struct node *np, mode_t type); corresponding child nodes. */ ino64_t procfs_make_ino (struct node *np, const char *filename); -error_t procfs_get_contents (struct node *np, char **data, size_t *data_len); +error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len); error_t procfs_lookup (struct node *np, const char *name, struct node **npp); void procfs_cleanup (struct node *np); diff --git a/procfs_dir.c b/procfs_dir.c index 4df4669..8ec3f7a 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -11,7 +11,7 @@ struct procfs_dir_node }; static error_t -procfs_dir_get_contents (void *hook, char **contents, size_t *contents_len) +procfs_dir_get_contents (void *hook, char **contents, ssize_t *contents_len) { static const char dot_dotdot[] = ".\0.."; struct procfs_dir_node *dn = hook; diff --git a/proclist.c b/proclist.c index b5acb26..38368fe 100644 --- a/proclist.c +++ b/proclist.c @@ -10,7 +10,7 @@ #define PID_STR_SIZE (3 * sizeof (pid_t) + 1) static error_t -proclist_get_contents (void *hook, char **contents, size_t *contents_len) +proclist_get_contents (void *hook, char **contents, ssize_t *contents_len) { struct ps_context *pc = hook; pidarray_t pids; diff --git a/rootdir.c b/rootdir.c index cd8949b..364b073 100644 --- a/rootdir.c +++ b/rootdir.c @@ -44,7 +44,7 @@ get_boottime (struct ps_context *pc, struct timeval *tv) } static error_t -rootdir_gc_version (void *hook, char **contents, size_t *contents_len) +rootdir_gc_version (void *hook, char **contents, ssize_t *contents_len) { struct utsname uts; int r; @@ -57,13 +57,13 @@ rootdir_gc_version (void *hook, char **contents, size_t *contents_len) "Linux version 2.6.1 (%s %s %s %s)\n", uts.sysname, uts.release, uts.version, uts.machine); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } /* Uptime -- we use the start time of init to deduce it. This is probably a bit fragile, as any clock update will make the result inaccurate. */ static error_t -rootdir_gc_uptime (void *hook, char **contents, size_t *contents_len) +rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) { struct timeval time, boottime; double up_secs; @@ -87,11 +87,11 @@ rootdir_gc_uptime (void *hook, char **contents, size_t *contents_len) and there to make that work. */ *contents_len = asprintf (contents, "%.2lf %.2lf\n", up_secs, up_secs); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_stat (void *hook, char **contents, size_t *contents_len) +rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) { struct timeval boottime, time; struct vm_statistics vmstats; @@ -126,11 +126,11 @@ rootdir_gc_stat (void *hook, char **contents, size_t *contents_len) vmstats.pageins, vmstats.pageouts, boottime.tv_sec); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_loadavg (void *hook, char **contents, size_t *contents_len) +rootdir_gc_loadavg (void *hook, char **contents, ssize_t *contents_len) { host_load_info_data_t hli; mach_msg_type_number_t cnt; @@ -148,11 +148,11 @@ rootdir_gc_loadavg (void *hook, char **contents, size_t *contents_len) hli.avenrun[1] / (double) LOAD_SCALE, hli.avenrun[2] / (double) LOAD_SCALE); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_meminfo (void *hook, char **contents, size_t *contents_len) +rootdir_gc_meminfo (void *hook, char **contents, ssize_t *contents_len) { host_basic_info_data_t hbi; mach_msg_type_number_t cnt; @@ -183,11 +183,11 @@ rootdir_gc_meminfo (void *hook, char **contents, size_t *contents_len) (long unsigned) vmstats.inactive_count * PAGE_SIZE / 1024, (long unsigned) vmstats.wire_count * PAGE_SIZE / 1024); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_vmstat (void *hook, char **contents, size_t *contents_len) +rootdir_gc_vmstat (void *hook, char **contents, ssize_t *contents_len) { host_basic_info_data_t hbi; mach_msg_type_number_t cnt; @@ -228,11 +228,11 @@ rootdir_gc_vmstat (void *hook, char **contents, size_t *contents_len) (long unsigned) vmstats.pageouts, (long unsigned) vmstats.faults); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_cmdline (void *hook, char **contents, size_t *contents_len) +rootdir_gc_cmdline (void *hook, char **contents, ssize_t *contents_len) { struct ps_context *pc = hook; struct proc_stat *ps; @@ -267,10 +267,10 @@ out: } static error_t -rootdir_gc_fakeself (void *hook, char **contents, size_t *contents_len) +rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) { *contents_len = asprintf (contents, "%d", opt_fake_self); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } -- cgit v1.2.3