mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-27 06:21:08 +00:00
Free allocated configuration memory
Most of these were found with valgrind by repeatedly doing lxc_container_new followed by lxc_container_put. Also free memory when config items are re-parsed, as happens when lxcapi_set_config_item() is called. Refactored path type config items to use a common underlying routine. Signed-off-by: Dwight Engen <dwight.engen@oracle.com> Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
This commit is contained in:
parent
9ebb03ad4a
commit
d95db067d2
@ -2473,6 +2473,7 @@ static void lxc_remove_nic(struct lxc_list *it)
|
|||||||
free(it2->elem);
|
free(it2->elem);
|
||||||
free(it2);
|
free(it2);
|
||||||
}
|
}
|
||||||
|
free(netdev);
|
||||||
free(it);
|
free(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2655,6 +2656,14 @@ void lxc_conf_free(struct lxc_conf *conf)
|
|||||||
free(conf->console.path);
|
free(conf->console.path);
|
||||||
if (conf->rootfs.mount != default_rootfs_mount)
|
if (conf->rootfs.mount != default_rootfs_mount)
|
||||||
free(conf->rootfs.mount);
|
free(conf->rootfs.mount);
|
||||||
|
if (conf->rootfs.path)
|
||||||
|
free(conf->rootfs.path);
|
||||||
|
if (conf->utsname)
|
||||||
|
free(conf->utsname);
|
||||||
|
if (conf->ttydir)
|
||||||
|
free(conf->ttydir);
|
||||||
|
if (conf->fstab)
|
||||||
|
free(conf->fstab);
|
||||||
lxc_clear_config_network(conf);
|
lxc_clear_config_network(conf);
|
||||||
#if HAVE_APPARMOR
|
#if HAVE_APPARMOR
|
||||||
if (conf->aa_profile)
|
if (conf->aa_profile)
|
||||||
|
@ -488,17 +488,21 @@ static int config_network_hwaddr(const char *key, char *value,
|
|||||||
struct lxc_conf *lxc_conf)
|
struct lxc_conf *lxc_conf)
|
||||||
{
|
{
|
||||||
struct lxc_netdev *netdev;
|
struct lxc_netdev *netdev;
|
||||||
|
char *hwaddr;
|
||||||
|
|
||||||
netdev = network_netdev(key, value, &lxc_conf->network);
|
netdev = network_netdev(key, value, &lxc_conf->network);
|
||||||
if (!netdev)
|
if (!netdev)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
netdev->hwaddr = strdup(value);
|
hwaddr = strdup(value);
|
||||||
if (!netdev->hwaddr) {
|
if (!hwaddr) {
|
||||||
SYSERROR("failed to dup string '%s'", value);
|
SYSERROR("failed to dup string '%s'", value);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (netdev->hwaddr)
|
||||||
|
free(netdev->hwaddr);
|
||||||
|
netdev->hwaddr = hwaddr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,17 +525,21 @@ static int config_network_mtu(const char *key, char *value,
|
|||||||
struct lxc_conf *lxc_conf)
|
struct lxc_conf *lxc_conf)
|
||||||
{
|
{
|
||||||
struct lxc_netdev *netdev;
|
struct lxc_netdev *netdev;
|
||||||
|
char *mtu;
|
||||||
|
|
||||||
netdev = network_netdev(key, value, &lxc_conf->network);
|
netdev = network_netdev(key, value, &lxc_conf->network);
|
||||||
if (!netdev)
|
if (!netdev)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
netdev->mtu = strdup(value);
|
mtu = strdup(value);
|
||||||
if (!netdev->mtu) {
|
if (!mtu) {
|
||||||
SYSERROR("failed to dup string '%s'", value);
|
SYSERROR("failed to dup string '%s'", value);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (netdev->mtu)
|
||||||
|
free(netdev->mtu);
|
||||||
|
netdev->mtu = mtu;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,6 +795,8 @@ static int config_seccomp(const char *key, char *value,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lxc_conf->seccomp)
|
||||||
|
free(lxc_conf->seccomp);
|
||||||
lxc_conf->seccomp = path;
|
lxc_conf->seccomp = path;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -859,6 +869,8 @@ static int config_ttydir(const char *key, char *value,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lxc_conf->ttydir)
|
||||||
|
free(lxc_conf->ttydir);
|
||||||
lxc_conf->ttydir = path;
|
lxc_conf->ttydir = path;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -877,6 +889,8 @@ static int config_aa_profile(const char *key, char *value, struct lxc_conf *lxc_
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lxc_conf->aa_profile)
|
||||||
|
free(lxc_conf->aa_profile);
|
||||||
lxc_conf->aa_profile = path;
|
lxc_conf->aa_profile = path;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -951,22 +965,33 @@ out:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_fstab(const char *key, char *value, struct lxc_conf *lxc_conf)
|
static int config_path_item(const char *key, const char *value,
|
||||||
|
struct lxc_conf *lxc_conf, char **conf_item)
|
||||||
{
|
{
|
||||||
|
char *valdup;
|
||||||
if (strlen(value) >= MAXPATHLEN) {
|
if (strlen(value) >= MAXPATHLEN) {
|
||||||
ERROR("%s path is too long", value);
|
ERROR("%s path is too long", value);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lxc_conf->fstab = strdup(value);
|
valdup = strdup(value);
|
||||||
if (!lxc_conf->fstab) {
|
if (!valdup) {
|
||||||
SYSERROR("failed to duplicate string %s", value);
|
SYSERROR("failed to duplicate string %s", value);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (*conf_item)
|
||||||
|
free(*conf_item);
|
||||||
|
*conf_item = valdup;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int config_fstab(const char *key, const char *value,
|
||||||
|
struct lxc_conf *lxc_conf)
|
||||||
|
{
|
||||||
|
return config_path_item(key, value, lxc_conf, &lxc_conf->fstab);
|
||||||
|
}
|
||||||
|
|
||||||
static int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
|
static int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
|
||||||
{
|
{
|
||||||
char *fstab_token = "lxc.mount";
|
char *fstab_token = "lxc.mount";
|
||||||
@ -1006,7 +1031,7 @@ static int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
|
|||||||
static int config_cap_drop(const char *key, char *value,
|
static int config_cap_drop(const char *key, char *value,
|
||||||
struct lxc_conf *lxc_conf)
|
struct lxc_conf *lxc_conf)
|
||||||
{
|
{
|
||||||
char *dropcaps, *sptr, *token;
|
char *dropcaps, *dropptr, *sptr, *token;
|
||||||
struct lxc_list *droplist;
|
struct lxc_list *droplist;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
@ -1021,13 +1046,12 @@ static int config_cap_drop(const char *key, char *value,
|
|||||||
|
|
||||||
/* in case several capability drop is specified in a single line
|
/* in case several capability drop is specified in a single line
|
||||||
* split these caps in a single element for the list */
|
* split these caps in a single element for the list */
|
||||||
for (;;) {
|
for (dropptr = dropcaps;;dropptr = NULL) {
|
||||||
token = strtok_r(dropcaps, " \t", &sptr);
|
token = strtok_r(dropptr, " \t", &sptr);
|
||||||
if (!token) {
|
if (!token) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dropcaps = NULL;
|
|
||||||
|
|
||||||
droplist = malloc(sizeof(*droplist));
|
droplist = malloc(sizeof(*droplist));
|
||||||
if (!droplist) {
|
if (!droplist) {
|
||||||
@ -1035,10 +1059,6 @@ static int config_cap_drop(const char *key, char *value,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* note - i do believe we're losing memory here,
|
|
||||||
note that token is already pointing into dropcaps
|
|
||||||
which is strdup'd. we never free that bit.
|
|
||||||
*/
|
|
||||||
droplist->elem = strdup(token);
|
droplist->elem = strdup(token);
|
||||||
if (!droplist->elem) {
|
if (!droplist->elem) {
|
||||||
SYSERROR("failed to dup '%s'", token);
|
SYSERROR("failed to dup '%s'", token);
|
||||||
@ -1065,6 +1085,8 @@ static int config_console(const char *key, char *value,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lxc_conf->console.path)
|
||||||
|
free(lxc_conf->console.path);
|
||||||
lxc_conf->console.path = path;
|
lxc_conf->console.path = path;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1078,50 +1100,17 @@ static int config_includefile(const char *key, char *value,
|
|||||||
|
|
||||||
static int config_rootfs(const char *key, char *value, struct lxc_conf *lxc_conf)
|
static int config_rootfs(const char *key, char *value, struct lxc_conf *lxc_conf)
|
||||||
{
|
{
|
||||||
if (strlen(value) >= MAXPATHLEN) {
|
return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.path);
|
||||||
ERROR("%s path is too long", value);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
lxc_conf->rootfs.path = strdup(value);
|
|
||||||
if (!lxc_conf->rootfs.path) {
|
|
||||||
SYSERROR("failed to duplicate string %s", value);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_rootfs_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
|
static int config_rootfs_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
|
||||||
{
|
{
|
||||||
if (strlen(value) >= MAXPATHLEN) {
|
return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.mount);
|
||||||
ERROR("%s path is too long", value);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
lxc_conf->rootfs.mount = strdup(value);
|
|
||||||
if (!lxc_conf->rootfs.mount) {
|
|
||||||
SYSERROR("failed to duplicate string '%s'", value);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_pivotdir(const char *key, char *value, struct lxc_conf *lxc_conf)
|
static int config_pivotdir(const char *key, char *value, struct lxc_conf *lxc_conf)
|
||||||
{
|
{
|
||||||
if (strlen(value) >= MAXPATHLEN) {
|
return config_path_item(key, value, lxc_conf, &lxc_conf->rootfs.pivot);
|
||||||
ERROR("%s path is too long", value);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
lxc_conf->rootfs.pivot = strdup(value);
|
|
||||||
if (!lxc_conf->rootfs.pivot) {
|
|
||||||
SYSERROR("failed to duplicate string %s", value);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_conf)
|
static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_conf)
|
||||||
@ -1141,6 +1130,8 @@ static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_con
|
|||||||
}
|
}
|
||||||
|
|
||||||
strcpy(utsname->nodename, value);
|
strcpy(utsname->nodename, value);
|
||||||
|
if (lxc_conf->utsname)
|
||||||
|
free(lxc_conf->utsname);
|
||||||
lxc_conf->utsname = utsname;
|
lxc_conf->utsname = utsname;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -65,6 +65,10 @@ static void lxc_container_free(struct lxc_container *c)
|
|||||||
free(c->error_string);
|
free(c->error_string);
|
||||||
c->error_string = NULL;
|
c->error_string = NULL;
|
||||||
}
|
}
|
||||||
|
if (c->slock) {
|
||||||
|
sem_close(c->slock);
|
||||||
|
c->slock = NULL;
|
||||||
|
}
|
||||||
if (c->privlock) {
|
if (c->privlock) {
|
||||||
sem_destroy(c->privlock);
|
sem_destroy(c->privlock);
|
||||||
free(c->privlock);
|
free(c->privlock);
|
||||||
@ -74,11 +78,10 @@ static void lxc_container_free(struct lxc_container *c)
|
|||||||
free(c->name);
|
free(c->name);
|
||||||
c->name = NULL;
|
c->name = NULL;
|
||||||
}
|
}
|
||||||
/*
|
if (c->lxc_conf) {
|
||||||
* XXX TODO
|
lxc_conf_free(c->lxc_conf);
|
||||||
* note, c->lxc_conf is going to have to be freed, but the fn
|
c->lxc_conf = NULL;
|
||||||
* to do that hasn't been written yet near as I can tell
|
}
|
||||||
*/
|
|
||||||
free(c);
|
free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user