Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: genl: fix error path memory leak in policy dumping

If construction of the array of policies fails when recording
non-first policy we need to unwind.

netlink_policy_dump_add_policy() itself also needs fixing as
it currently gives up on error without recording the allocated
pointer in the pstate pointer.

Reported-by: syzbot+dc54d9ba8153b216cae0@syzkaller.appspotmail.com
Fixes: 50a896cf2d6f ("genetlink: properly support per-op policy dumping")
Link: https://lore.kernel.org/r/20220816161939.577583-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+17 -3
+5 -1
net/netlink/genetlink.c
··· 1174 1174 op.policy, 1175 1175 op.maxattr); 1176 1176 if (err) 1177 - return err; 1177 + goto err_free_state; 1178 1178 } 1179 1179 } 1180 1180 1181 1181 if (!ctx->state) 1182 1182 return -ENODATA; 1183 1183 return 0; 1184 + 1185 + err_free_state: 1186 + netlink_policy_dump_free(ctx->state); 1187 + return err; 1184 1188 } 1185 1189 1186 1190 static void *ctrl_dumppolicy_prep(struct sk_buff *skb,
+12 -2
net/netlink/policy.c
··· 144 144 145 145 err = add_policy(&state, policy, maxtype); 146 146 if (err) 147 - return err; 147 + goto err_try_undo; 148 148 149 149 for (policy_idx = 0; 150 150 policy_idx < state->n_alloc && state->policies[policy_idx].policy; ··· 164 164 policy[type].nested_policy, 165 165 policy[type].len); 166 166 if (err) 167 - return err; 167 + goto err_try_undo; 168 168 break; 169 169 default: 170 170 break; ··· 174 174 175 175 *pstate = state; 176 176 return 0; 177 + 178 + err_try_undo: 179 + /* Try to preserve reasonable unwind semantics - if we're starting from 180 + * scratch clean up fully, otherwise record what we got and caller will. 181 + */ 182 + if (!*pstate) 183 + netlink_policy_dump_free(state); 184 + else 185 + *pstate = state; 186 + return err; 177 187 } 178 188 179 189 static bool