Bug Summary

File:src/usr.sbin/amd/amd/sched.c
Warning:line 81, column 13
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sched.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/amd/amd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/amd/amd/../rpcx -I /usr/src/usr.sbin/amd/amd/../include -D ARCH_REP="amd64" -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/amd/amd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/amd/amd/sched.c
1/* $OpenBSD: sched.c,v 1.18 2014/10/26 03:28:41 guenther Exp $ */
2
3/*
4 * Copyright (c) 1990 Jan-Simon Pendry
5 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
6 * Copyright (c) 1990, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * Jan-Simon Pendry at Imperial College, London.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: @(#)sched.c 8.1 (Berkeley) 6/6/93
37 * $Id: sched.c,v 1.18 2014/10/26 03:28:41 guenther Exp $
38 */
39
40/*
41 * Process scheduler
42 */
43
44#include "am.h"
45#include <signal.h>
46#include <sys/wait.h>
47#include <setjmp.h>
48extern jmp_buf select_intr;
49extern int select_intr_valid;
50
51typedef struct pjob pjob;
52struct pjob {
53 qelem hdr; /* Linked list */
54 pid_t pid; /* Process ID of job */
55 cb_fun cb_fun; /* Callback function */
56 void *cb_closure; /* Closure for callback */
57 int w; /* Status filled in by sigchld */
58 void *wchan; /* Wait channel */
59};
60
61extern qelem proc_list_head;
62qelem proc_list_head = { &proc_list_head, &proc_list_head };
63extern qelem proc_wait_list;
64qelem proc_wait_list = { &proc_wait_list, &proc_wait_list };
65
66int task_notify_todo;
67
68void
69ins_que(qelem *elem, qelem *pred)
70{
71 qelem *p = pred->q_forw;
72 elem->q_back = pred;
73 elem->q_forw = p;
74 pred->q_forw = elem;
75 p->q_back = elem;
76}
77
78void
79rem_que(qelem *elem)
80{
81 qelem *p = elem->q_forw;
7
Use of memory after it is freed
82 qelem *p2 = elem->q_back;
83 p2->q_forw = p;
84 p->q_back = p2;
85}
86
87static pjob *
88sched_job(cb_fun cf, void *ca)
89{
90 pjob *p = ALLOC(pjob)((struct pjob *) xmalloc(sizeof(struct pjob)));
91
92 p->cb_fun = cf;
93 p->cb_closure = ca;
94
95 /*
96 * Now place on wait queue
97 */
98 ins_que(&p->hdr, &proc_wait_list);
99
100 return p;
101}
102
103void
104run_task(task_fun tf, void *ta, cb_fun cf, void *ca)
105{
106 pjob *p = sched_job(cf, ca);
107 sigset_t mask, omask;
108
109 p->wchan = p;
110
111 sigemptyset(&mask);
112 sigaddset(&mask, SIGCHLD20);
113 sigprocmask(SIG_BLOCK1, &mask, &omask);
114
115 if ((p->pid = background())) {
116 sigprocmask(SIG_SETMASK3, &omask, NULL((void *)0));
117 return;
118 }
119
120 exit((*tf)(ta));
121 /* firewall... */
122 abort();
123}
124
125/*
126 * Schedule a task to be run when woken up
127 */
128void
129sched_task(cb_fun cf, void *ca, void *wchan)
130{
131 /*
132 * Allocate a new task
133 */
134 pjob *p = sched_job(cf, ca);
135#ifdef DEBUG_SLEEP
136 dlog("SLEEP on %#x", wchan);
137#endif
138 p->wchan = wchan;
139 p->pid = 0;
140 bzero(&p->w, sizeof(p->w));
141}
142
143static void
144wakeupjob(pjob *p)
145{
146 rem_que(&p->hdr);
147 ins_que(&p->hdr, &proc_list_head);
148 task_notify_todo++;
149}
150
151void
152wakeup(void *wchan)
153{
154 pjob *p, *p2;
155#ifdef DEBUG_SLEEP
156 int done = 0;
157#endif
158 if (!foreground)
159 return;
160
161#ifdef DEBUG_SLEEP
162 /*dlog("wakeup(%#x)", wchan);*/
163#endif
164 /*
165 * Can't user ITER() here because
166 * wakeupjob() juggles the list.
167 */
168 for (p = FIRST(pjob, &proc_wait_list)((pjob *) ((&proc_wait_list)->q_forw));
169 p2 = NEXT(pjob, p)((pjob *) (((qelem *) p)->q_forw)), p != HEAD(pjob, &proc_wait_list)((pjob *) &proc_wait_list);
170 p = p2) {
171 if (p->wchan == wchan) {
172#ifdef DEBUG_SLEEP
173 done = 1;
174#endif
175 wakeupjob(p);
176 }
177 }
178
179#ifdef DEBUG_SLEEP
180 if (!done)
181 dlog("Nothing SLEEPing on %#x", wchan);
182#endif
183}
184
185void
186wakeup_task(int rc, int term, void *cl)
187{
188 wakeup(cl);
189}
190
191
192void
193sigchld(int sig)
194{
195 int w;
196 int save_errno = errno(*__errno());
197 pid_t pid;
198
199 while ((pid = waitpid((pid_t)-1, &w, WNOHANG1)) > 0) {
200 pjob *p, *p2;
201
202 if (WIFSIGNALED(w)(((w) & 0177) != 0177 && ((w) & 0177) != 0))
203 plog(XLOG_ERROR0x0002, "Process %ld exited with signal %d",
204 (long)pid, WTERMSIG(w)(((w) & 0177)));
205#ifdef DEBUG
206 else
207 dlog("Process %ld exited with status %d",
208 (long)pid, WEXITSTATUS(w)(int)(((unsigned)(w) >> 8) & 0xff));
209#endif /* DEBUG */
210
211 for (p = FIRST(pjob, &proc_wait_list)((pjob *) ((&proc_wait_list)->q_forw));
212 p2 = NEXT(pjob, p)((pjob *) (((qelem *) p)->q_forw)), p != HEAD(pjob, &proc_wait_list)((pjob *) &proc_wait_list);
213 p = p2) {
214 if (p->pid == pid) {
215 p->w = w;
216 wakeupjob(p);
217 break;
218 }
219 }
220
221#ifdef DEBUG
222 if (p == NULL((void *)0))
223 dlog("can't locate task block for pid %ld", (long)pid);
224#endif /* DEBUG */
225 }
226
227 if (select_intr_valid)
228 longjmp(select_intr, sig);
229 errno(*__errno()) = save_errno;
230}
231
232/*
233 * Run any pending tasks.
234 * This must be called with SIGCHLD disabled
235 */
236void
237do_task_notify(void)
238{
239 /*
240 * Keep taking the first item off the list and processing it.
241 *
242 * Done this way because the callback can, quite reasonably,
243 * queue a new task, so no local reference into the list can be
244 * held here.
245 */
246 while (FIRST(pjob, &proc_list_head)((pjob *) ((&proc_list_head)->q_forw)) != HEAD(pjob, &proc_list_head)((pjob *) &proc_list_head)) {
1
Loop condition is true. Entering loop body
5
Loop condition is true. Entering loop body
247 pjob *p = FIRST(pjob, &proc_list_head)((pjob *) ((&proc_list_head)->q_forw));
248 rem_que(&p->hdr);
6
Calling 'rem_que'
249 /*
250 * This job has completed
251 */
252 --task_notify_todo;
253
254 /*
255 * Do callback if it exists
256 */
257 if (p->cb_fun)
2
Assuming field 'cb_fun' is null
3
Taking false branch
258 (*p->cb_fun)(WIFEXITED(p->w)(((p->w) & 0177) == 0) ? WEXITSTATUS(p->w)(int)(((unsigned)(p->w) >> 8) & 0xff) : 0,
259 WIFSIGNALED(p->w)(((p->w) & 0177) != 0177 && ((p->w) & 0177
) != 0)
? WTERMSIG(p->w)(((p->w) & 0177)) : 0,
260 p->cb_closure);
261
262 free(p);
4
Memory is released
263 }
264}