Download raw body.
[patch 1 of 3] iscsid(8): fix memory leak
On Tue, Dec 31, 2024 at 06:30:02PM +1030, Jack Burton wrote:
> Fix memory leaks in some members of struct kvp.
>
> It looks like this is what claudio@ originally intended the otherwise
> unused flags member (which has been in the tree since iscsid was first
> added 14 years ago) to be used for.
>
> This patch will make very little difference as things stand (as in a
> typical run the leaks are tiny), but this approach is necessary for
> the third patch in my set, which makes much heavier use of struct kvp
> members allocated on the heap.
>
> Almost all of this patch is also included in my third patch (all
> bar the bits the third patch makes obsolete), but I'm posting this
> one on its own first as it has a different purpose (this one's a
> bug fix; whereas patch 3 introduces new functionality).
>
> cvs server: Diffing .
> Index: connection.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/iscsid/connection.c,v
> diff -u -p -r1.21 connection.c
> --- connection.c 5 Dec 2015 06:38:18 -0000 1.21
> +++ connection.c 30 Dec 2024 05:56:32 -0000
> @@ -327,11 +327,13 @@ conn_gen_kvp(struct connection *c, struc
> kvp[i].key = strdup("MaxConnections");
I think here it would make sense to kill the strdup and the
KVP_KEY_ALLOCED. Since the key can be a static string.
> if (kvp[i].key == NULL)
> return -1;
> + kvp[i].flags |= KVP_KEY_ALLOCED;
> if (asprintf(&kvp[i].value, "%hu",
> s->mine.MaxConnections) == -1) {
> kvp[i].value = NULL;
> return -1;
> }
> + kvp[i].flags |= KVP_VALUE_ALLOCED;
> }
> i++;
> }
> @@ -341,11 +343,13 @@ conn_gen_kvp(struct connection *c, struc
> kvp[i].key = strdup("MaxRecvDataSegmentLength");
Same here.
> if (kvp[i].key == NULL)
> return -1;
> + kvp[i].flags |= KVP_KEY_ALLOCED;
> if (asprintf(&kvp[i].value, "%u",
> c->mine.MaxRecvDataSegmentLength) == -1) {
> kvp[i].value = NULL;
> return -1;
> }
> + kvp[i].flags |= KVP_VALUE_ALLOCED;
> }
> i++;
> }
> Index: initiator.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/iscsid/initiator.c,v
> diff -u -p -r1.15 initiator.c
> --- initiator.c 16 Jan 2015 15:57:06 -0000 1.15
> +++ initiator.c 30 Dec 2024 05:56:32 -0000
> @@ -280,7 +280,7 @@ initiator_login_kvp(struct connection *c
> if (!(kvp = calloc(nkvp, sizeof(*kvp))))
> return NULL;
> if (conn_gen_kvp(c, kvp, &nkvp) == -1) {
> - free(kvp);
> + kvp_free(kvp);
> return NULL;
> }
> break;
> @@ -327,10 +327,10 @@ initiator_login_build(struct connection
> return NULL;
> }
> if ((n = text_to_pdu(kvp, p)) == -1) {
> - free(kvp);
> + kvp_free(kvp);
> return NULL;
> }
> - free(kvp);
> + kvp_free(kvp);
>
> if (n > 8192) {
> log_warn("initiator_login_build: help, I'm too verbose");
> @@ -409,11 +409,11 @@ initiator_login_cb(struct connection *c,
> }
>
> if (conn_parse_kvp(c, kvp) == -1) {
> - free(kvp);
> + kvp_free(kvp);
> conn_fail(c);
> goto done;
> }
> - free(kvp);
> + kvp_free(kvp);
> }
>
> /* advance FSM if possible */
> @@ -480,7 +480,7 @@ initiator_discovery_cb(struct connection
> for (k = kvp; k->key; k++) {
> log_debug("%s\t=>\t%s", k->key, k->value);
> }
> - free(kvp);
> + kvp_free(kvp);
> session_shutdown(c->session);
> break;
> default:
> Index: iscsid.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/iscsid/iscsid.h,v
> diff -u -p -r1.19 iscsid.h
> --- iscsid.h 21 May 2024 05:00:48 -0000 1.19
> +++ iscsid.h 30 Dec 2024 05:56:33 -0000
> @@ -385,6 +385,7 @@ void *pdu_getbuf(struct pdu *, size_t *,
> void pdu_free(struct pdu *);
> int socket_setblockmode(int, int);
> const char *log_sockaddr(void *);
> +void kvp_free(struct kvp *);
>
> void task_init(struct task *, struct session *, int, void *,
> void (*)(struct connection *, void *, struct pdu *),
> Index: util.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/iscsid/util.c,v
> diff -u -p -r1.9 util.c
> --- util.c 12 Apr 2021 10:03:33 -0000 1.9
> +++ util.c 30 Dec 2024 05:56:33 -0000
> @@ -189,3 +189,19 @@ fail:
> pdu_free(pdu);
> return -1;
> }
> +
> +void
> +kvp_free(struct kvp *kvp)
> +{
> + struct kvp *k;
> +
> + if (kvp == NULL)
> + return;
> + for (k = kvp; k->key; k++) {
> + if (k->flags & KVP_KEY_ALLOCED)
> + free(k->key);
> + if (k->flags & KVP_VALUE_ALLOCED)
> + free(k->value);
> + }
> + free(kvp);
> +}
>
I wonder if pdu_to_text() should actually alloc the kvp key and value
instead of fiddling with the pdu buffer internals.
I will commit this diff with the above mentioned changes tomorrow.
--
:wq Claudio
[patch 1 of 3] iscsid(8): fix memory leak