Skip to content

Commit b64ee48

Browse files
committed
Merge branch 'act_gate-fixes'
Davide Caratti says: ==================== two fixes for 'act_gate' control plane - patch 1/2 attempts to fix the error path of tcf_gate_init() when users try to configure 'act_gate' rules with wrong parameters - patch 2/2 is a follow-up of a recent fix for NULL dereference in the error path of tcf_gate_init() further work will introduce a tdc test for 'act_gate'. changes since v2: - fix undefined behavior in patch 1/2 - improve comment in patch 2/2 changes since v1: coding style fixes in patch 1/2 and 2/2 ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents ba61539 + c362a06 commit b64ee48

File tree

1 file changed

+68
-58
lines changed

1 file changed

+68
-58
lines changed

net/sched/act_gate.c

Lines changed: 68 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static ktime_t gate_get_time(struct tcf_gate *gact)
3232
return KTIME_MAX;
3333
}
3434

35-
static int gate_get_start_time(struct tcf_gate *gact, ktime_t *start)
35+
static void gate_get_start_time(struct tcf_gate *gact, ktime_t *start)
3636
{
3737
struct tcf_gate_params *param = &gact->param;
3838
ktime_t now, base, cycle;
@@ -43,18 +43,13 @@ static int gate_get_start_time(struct tcf_gate *gact, ktime_t *start)
4343

4444
if (ktime_after(base, now)) {
4545
*start = base;
46-
return 0;
46+
return;
4747
}
4848

4949
cycle = param->tcfg_cycletime;
5050

51-
/* cycle time should not be zero */
52-
if (!cycle)
53-
return -EFAULT;
54-
5551
n = div64_u64(ktime_sub_ns(now, base), cycle);
5652
*start = ktime_add_ns(base, (n + 1) * cycle);
57-
return 0;
5853
}
5954

6055
static void gate_start_timer(struct tcf_gate *gact, ktime_t start)
@@ -277,6 +272,27 @@ static int parse_gate_list(struct nlattr *list_attr,
277272
return err;
278273
}
279274

275+
static void gate_setup_timer(struct tcf_gate *gact, u64 basetime,
276+
enum tk_offsets tko, s32 clockid,
277+
bool do_init)
278+
{
279+
if (!do_init) {
280+
if (basetime == gact->param.tcfg_basetime &&
281+
tko == gact->tk_offset &&
282+
clockid == gact->param.tcfg_clockid)
283+
return;
284+
285+
spin_unlock_bh(&gact->tcf_lock);
286+
hrtimer_cancel(&gact->hitimer);
287+
spin_lock_bh(&gact->tcf_lock);
288+
}
289+
gact->param.tcfg_basetime = basetime;
290+
gact->param.tcfg_clockid = clockid;
291+
gact->tk_offset = tko;
292+
hrtimer_init(&gact->hitimer, clockid, HRTIMER_MODE_ABS_SOFT);
293+
gact->hitimer.function = gate_timer_func;
294+
}
295+
280296
static int tcf_gate_init(struct net *net, struct nlattr *nla,
281297
struct nlattr *est, struct tc_action **a,
282298
int ovr, int bind, bool rtnl_held,
@@ -287,12 +303,12 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
287303
enum tk_offsets tk_offset = TK_OFFS_TAI;
288304
struct nlattr *tb[TCA_GATE_MAX + 1];
289305
struct tcf_chain *goto_ch = NULL;
306+
u64 cycletime = 0, basetime = 0;
290307
struct tcf_gate_params *p;
291308
s32 clockid = CLOCK_TAI;
292309
struct tcf_gate *gact;
293310
struct tc_gate *parm;
294311
int ret = 0, err;
295-
u64 basetime = 0;
296312
u32 gflags = 0;
297313
s32 prio = -1;
298314
ktime_t start;
@@ -308,6 +324,27 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
308324
if (!tb[TCA_GATE_PARMS])
309325
return -EINVAL;
310326

327+
if (tb[TCA_GATE_CLOCKID]) {
328+
clockid = nla_get_s32(tb[TCA_GATE_CLOCKID]);
329+
switch (clockid) {
330+
case CLOCK_REALTIME:
331+
tk_offset = TK_OFFS_REAL;
332+
break;
333+
case CLOCK_MONOTONIC:
334+
tk_offset = TK_OFFS_MAX;
335+
break;
336+
case CLOCK_BOOTTIME:
337+
tk_offset = TK_OFFS_BOOT;
338+
break;
339+
case CLOCK_TAI:
340+
tk_offset = TK_OFFS_TAI;
341+
break;
342+
default:
343+
NL_SET_ERR_MSG(extack, "Invalid 'clockid'");
344+
return -EINVAL;
345+
}
346+
}
347+
311348
parm = nla_data(tb[TCA_GATE_PARMS]);
312349
index = parm->index;
313350

@@ -331,10 +368,6 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
331368
tcf_idr_release(*a, bind);
332369
return -EEXIST;
333370
}
334-
if (ret == ACT_P_CREATED) {
335-
to_gate(*a)->param.tcfg_clockid = -1;
336-
INIT_LIST_HEAD(&(to_gate(*a)->param.entries));
337-
}
338371

339372
if (tb[TCA_GATE_PRIORITY])
340373
prio = nla_get_s32(tb[TCA_GATE_PRIORITY]);
@@ -345,77 +378,49 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
345378
if (tb[TCA_GATE_FLAGS])
346379
gflags = nla_get_u32(tb[TCA_GATE_FLAGS]);
347380

348-
if (tb[TCA_GATE_CLOCKID]) {
349-
clockid = nla_get_s32(tb[TCA_GATE_CLOCKID]);
350-
switch (clockid) {
351-
case CLOCK_REALTIME:
352-
tk_offset = TK_OFFS_REAL;
353-
break;
354-
case CLOCK_MONOTONIC:
355-
tk_offset = TK_OFFS_MAX;
356-
break;
357-
case CLOCK_BOOTTIME:
358-
tk_offset = TK_OFFS_BOOT;
359-
break;
360-
case CLOCK_TAI:
361-
tk_offset = TK_OFFS_TAI;
362-
break;
363-
default:
364-
NL_SET_ERR_MSG(extack, "Invalid 'clockid'");
365-
goto release_idr;
366-
}
367-
}
381+
gact = to_gate(*a);
382+
if (ret == ACT_P_CREATED)
383+
INIT_LIST_HEAD(&gact->param.entries);
368384

369385
err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
370386
if (err < 0)
371387
goto release_idr;
372388

373-
gact = to_gate(*a);
374-
375389
spin_lock_bh(&gact->tcf_lock);
376390
p = &gact->param;
377391

378-
if (tb[TCA_GATE_CYCLE_TIME]) {
379-
p->tcfg_cycletime = nla_get_u64(tb[TCA_GATE_CYCLE_TIME]);
380-
if (!p->tcfg_cycletime_ext)
381-
goto chain_put;
382-
}
392+
if (tb[TCA_GATE_CYCLE_TIME])
393+
cycletime = nla_get_u64(tb[TCA_GATE_CYCLE_TIME]);
383394

384395
if (tb[TCA_GATE_ENTRY_LIST]) {
385396
err = parse_gate_list(tb[TCA_GATE_ENTRY_LIST], p, extack);
386397
if (err < 0)
387398
goto chain_put;
388399
}
389400

390-
if (!p->tcfg_cycletime) {
401+
if (!cycletime) {
391402
struct tcfg_gate_entry *entry;
392403
ktime_t cycle = 0;
393404

394405
list_for_each_entry(entry, &p->entries, list)
395406
cycle = ktime_add_ns(cycle, entry->interval);
396-
p->tcfg_cycletime = cycle;
407+
cycletime = cycle;
408+
if (!cycletime) {
409+
err = -EINVAL;
410+
goto chain_put;
411+
}
397412
}
413+
p->tcfg_cycletime = cycletime;
398414

399415
if (tb[TCA_GATE_CYCLE_TIME_EXT])
400416
p->tcfg_cycletime_ext =
401417
nla_get_u64(tb[TCA_GATE_CYCLE_TIME_EXT]);
402418

419+
gate_setup_timer(gact, basetime, tk_offset, clockid,
420+
ret == ACT_P_CREATED);
403421
p->tcfg_priority = prio;
404-
p->tcfg_basetime = basetime;
405-
p->tcfg_clockid = clockid;
406422
p->tcfg_flags = gflags;
407-
408-
gact->tk_offset = tk_offset;
409-
hrtimer_init(&gact->hitimer, clockid, HRTIMER_MODE_ABS_SOFT);
410-
gact->hitimer.function = gate_timer_func;
411-
412-
err = gate_get_start_time(gact, &start);
413-
if (err < 0) {
414-
NL_SET_ERR_MSG(extack,
415-
"Internal error: failed get start time");
416-
release_entry_list(&p->entries);
417-
goto chain_put;
418-
}
423+
gate_get_start_time(gact, &start);
419424

420425
gact->current_close_time = start;
421426
gact->current_gate_status = GATE_ACT_GATE_OPEN | GATE_ACT_PENDING;
@@ -443,6 +448,13 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
443448
if (goto_ch)
444449
tcf_chain_put_by_act(goto_ch);
445450
release_idr:
451+
/* action is not inserted in any list: it's safe to init hitimer
452+
* without taking tcf_lock.
453+
*/
454+
if (ret == ACT_P_CREATED)
455+
gate_setup_timer(gact, gact->param.tcfg_basetime,
456+
gact->tk_offset, gact->param.tcfg_clockid,
457+
true);
446458
tcf_idr_release(*a, bind);
447459
return err;
448460
}
@@ -453,9 +465,7 @@ static void tcf_gate_cleanup(struct tc_action *a)
453465
struct tcf_gate_params *p;
454466

455467
p = &gact->param;
456-
if (p->tcfg_clockid != -1)
457-
hrtimer_cancel(&gact->hitimer);
458-
468+
hrtimer_cancel(&gact->hitimer);
459469
release_entry_list(&p->entries);
460470
}
461471

0 commit comments

Comments
 (0)