Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch for "got root" kernel bug (n_tty: Fix n_tty_write crash when echoing in raw mode) #5

Open
wants to merge 6 commits into
base: kitkat
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion arch/arm/configs/evervolv_bravo_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ CONFIG_SWAP=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
CONFIG_HAVE_GENERIC_HARDIRQS=y

#
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,9 @@ validate_event(struct cpu_hw_events *cpuc,
{
struct hw_perf_event fake_event = event->hw;

if (is_software_event(event))
return 1;

if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
return 1;

Expand Down
3 changes: 3 additions & 0 deletions drivers/tty/n_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -1980,8 +1980,11 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
if (tty->ops->flush_chars)
tty->ops->flush_chars(tty);
} else {

while (nr > 0) {
mutex_lock(&tty->output_lock);
c = tty->ops->write(tty, b, nr);
mutex_unlock(&tty->output_lock);
if (c < 0) {
retval = c;
goto break_out;
Expand Down
2 changes: 1 addition & 1 deletion include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1490,7 +1490,7 @@ int write_one_page(struct page *page, int wait);
void task_dirty_inc(struct task_struct *tsk);

/* readahead.c */
#define VM_MAX_READAHEAD 128 /* kbytes */
#define VM_MAX_READAHEAD 2048 /* kbytes */
#define VM_MIN_READAHEAD 16 /* kbytes (includes current page) */

int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
Expand Down
1 change: 1 addition & 0 deletions include/linux/pkt_sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ struct tc_fifo_qopt {
struct tc_prio_qopt {
int bands; /* Number of bands */
__u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
__u8 enable_flow; /* Enable dequeue */
};

/* MULTIQ section */
Expand Down
25 changes: 25 additions & 0 deletions kernel/futex.c
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,13 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
u32 curval2;

if (requeue_pi) {
/*
* Requeue PI only works on two distinct uaddrs. This
* check is only valid for private futexes. See below.
*/
if (uaddr1 == uaddr2)
return -EINVAL;

/*
* requeue_pi requires a pi_state, try to allocate it now
* without any locks in case it fails.
Expand Down Expand Up @@ -1271,6 +1278,15 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
if (unlikely(ret != 0))
goto out_put_key1;

/*
* The check above which compares uaddrs is not sufficient for
* shared futexes. We need to compare the keys:
*/
if (requeue_pi && match_futex(&key1, &key2)) {
ret = -EINVAL;
goto out_put_keys;
}

hb1 = hash_futex(&key1);
hb2 = hash_futex(&key2);

Expand Down Expand Up @@ -2288,6 +2304,15 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
if (ret)
goto out_key2;

/*
* The check above which compares uaddrs is not sufficient for
* shared futexes. We need to compare the keys:
*/
if (match_futex(&q.key, &key2)) {
ret = -EINVAL;
goto out_put_keys;
}

/* Queue the futex_q, drop the hb lock, wait for wakeup. */
futex_wait_queue_me(hb, &q, to);

Expand Down
10 changes: 10 additions & 0 deletions net/sched/sch_prio.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct prio_sched_data
struct tcf_proto *filter_list;
u8 prio2band[TC_PRIO_MAX+1];
struct Qdisc *queues[TCQ_PRIO_BANDS];
u8 enable_flow;
};


Expand Down Expand Up @@ -97,6 +98,9 @@ static struct sk_buff *prio_peek(struct Qdisc *sch)
struct prio_sched_data *q = qdisc_priv(sch);
int prio;

if (!q->enable_flow)
return NULL;

for (prio = 0; prio < q->bands; prio++) {
struct Qdisc *qdisc = q->queues[prio];
struct sk_buff *skb = qdisc->ops->peek(qdisc);
Expand All @@ -111,6 +115,9 @@ static struct sk_buff *prio_dequeue(struct Qdisc* sch)
struct prio_sched_data *q = qdisc_priv(sch);
int prio;

if (!q->enable_flow)
return NULL;

for (prio = 0; prio < q->bands; prio++) {
struct Qdisc *qdisc = q->queues[prio];
struct sk_buff *skb = qdisc->dequeue(qdisc);
Expand Down Expand Up @@ -151,6 +158,7 @@ prio_reset(struct Qdisc* sch)
for (prio=0; prio<q->bands; prio++)
qdisc_reset(q->queues[prio]);
sch->q.qlen = 0;
q->enable_flow = 1;
}

static void
Expand Down Expand Up @@ -183,6 +191,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt)
}

sch_tree_lock(sch);
q->enable_flow = qopt->enable_flow;
q->bands = qopt->bands;
memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);

Expand Down Expand Up @@ -245,6 +254,7 @@ static int prio_dump(struct Qdisc *sch, struct sk_buff *skb)
struct tc_prio_qopt opt;

opt.bands = q->bands;
opt.enable_flow = q->enable_flow;
memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX+1);

NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
Expand Down