Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a569231 authored by Takashi Iwai's avatar Takashi Iwai Committed by Greg Kroah-Hartman
Browse files

ALSA: ctxfi: Fix out-of-range access

commit 76c47183224c86e4011048b80f0e2d0d166f01c2 upstream.

The master and next_conj of rcs_ops are used for iterating the
resource list entries, and currently those are supposed to return the
current value.  The problem is that next_conf may go over the last
entry before the loop abort condition is evaluated, and it may return
the "current" value that is beyond the array size.  It was caught
recently as a GPF, for example.

Those return values are, however, never actually evaluated, hence
basically we don't have to consider the current value as the return at
all.  By dropping those return values, the potential out-of-range
access above is also fixed automatically.

This patch changes the return type of master and next_conj callbacks
to void and drop the superfluous code accordingly.

BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214985
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20211118215729.26257-1-tiwai@suse.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 404fb109
Loading
Loading
Loading
Loading
+6 −8
Original line number Original line Diff line number Diff line
@@ -27,16 +27,15 @@


#define BLANK_SLOT		4094
#define BLANK_SLOT		4094


static int amixer_master(struct rsc *rsc)
static void amixer_master(struct rsc *rsc)
{
{
	rsc->conj = 0;
	rsc->conj = 0;
	return rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0];
	rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0];
}
}


static int amixer_next_conj(struct rsc *rsc)
static void amixer_next_conj(struct rsc *rsc)
{
{
	rsc->conj++;
	rsc->conj++;
	return container_of(rsc, struct amixer, rsc)->idx[rsc->conj];
}
}


static int amixer_index(const struct rsc *rsc)
static int amixer_index(const struct rsc *rsc)
@@ -335,16 +334,15 @@ int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr)


/* SUM resource management */
/* SUM resource management */


static int sum_master(struct rsc *rsc)
static void sum_master(struct rsc *rsc)
{
{
	rsc->conj = 0;
	rsc->conj = 0;
	return rsc->idx = container_of(rsc, struct sum, rsc)->idx[0];
	rsc->idx = container_of(rsc, struct sum, rsc)->idx[0];
}
}


static int sum_next_conj(struct rsc *rsc)
static void sum_next_conj(struct rsc *rsc)
{
{
	rsc->conj++;
	rsc->conj++;
	return container_of(rsc, struct sum, rsc)->idx[rsc->conj];
}
}


static int sum_index(const struct rsc *rsc)
static int sum_index(const struct rsc *rsc)
+8 −8
Original line number Original line Diff line number Diff line
@@ -55,12 +55,12 @@ static struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
	[SPDIFIO] = {.left = 0x05, .right = 0x85},
	[SPDIFIO] = {.left = 0x05, .right = 0x85},
};
};


static int daio_master(struct rsc *rsc)
static void daio_master(struct rsc *rsc)
{
{
	/* Actually, this is not the resource index of DAIO.
	/* Actually, this is not the resource index of DAIO.
	 * For DAO, it is the input mapper index. And, for DAI,
	 * For DAO, it is the input mapper index. And, for DAI,
	 * it is the output time-slot index. */
	 * it is the output time-slot index. */
	return rsc->conj = rsc->idx;
	rsc->conj = rsc->idx;
}
}


static int daio_index(const struct rsc *rsc)
static int daio_index(const struct rsc *rsc)
@@ -68,19 +68,19 @@ static int daio_index(const struct rsc *rsc)
	return rsc->conj;
	return rsc->conj;
}
}


static int daio_out_next_conj(struct rsc *rsc)
static void daio_out_next_conj(struct rsc *rsc)
{
{
	return rsc->conj += 2;
	rsc->conj += 2;
}
}


static int daio_in_next_conj_20k1(struct rsc *rsc)
static void daio_in_next_conj_20k1(struct rsc *rsc)
{
{
	return rsc->conj += 0x200;
	rsc->conj += 0x200;
}
}


static int daio_in_next_conj_20k2(struct rsc *rsc)
static void daio_in_next_conj_20k2(struct rsc *rsc)
{
{
	return rsc->conj += 0x100;
	rsc->conj += 0x100;
}
}


static const struct rsc_ops daio_out_rsc_ops = {
static const struct rsc_ops daio_out_rsc_ops = {
+3 −4
Original line number Original line Diff line number Diff line
@@ -113,18 +113,17 @@ static int audio_ring_slot(const struct rsc *rsc)
    return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
    return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
}
}


static int rsc_next_conj(struct rsc *rsc)
static void rsc_next_conj(struct rsc *rsc)
{
{
	unsigned int i;
	unsigned int i;
	for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
	for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
		i++;
		i++;
	rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
	rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
	return rsc->conj;
}
}


static int rsc_master(struct rsc *rsc)
static void rsc_master(struct rsc *rsc)
{
{
	return rsc->conj = rsc->idx;
	rsc->conj = rsc->idx;
}
}


static const struct rsc_ops rsc_generic_ops = {
static const struct rsc_ops rsc_generic_ops = {
+2 −2
Original line number Original line Diff line number Diff line
@@ -43,8 +43,8 @@ struct rsc {
};
};


struct rsc_ops {
struct rsc_ops {
	int (*master)(struct rsc *rsc);	/* Move to master resource */
	void (*master)(struct rsc *rsc); /* Move to master resource */
	int (*next_conj)(struct rsc *rsc); /* Move to next conjugate resource */
	void (*next_conj)(struct rsc *rsc); /* Move to next conjugate resource */
	int (*index)(const struct rsc *rsc); /* Return the index of resource */
	int (*index)(const struct rsc *rsc); /* Return the index of resource */
	/* Return the output slot number */
	/* Return the output slot number */
	int (*output_slot)(const struct rsc *rsc);
	int (*output_slot)(const struct rsc *rsc);
+3 −4
Original line number Original line Diff line number Diff line
@@ -594,16 +594,15 @@ int src_mgr_destroy(struct src_mgr *src_mgr)


/* SRCIMP resource manager operations */
/* SRCIMP resource manager operations */


static int srcimp_master(struct rsc *rsc)
static void srcimp_master(struct rsc *rsc)
{
{
	rsc->conj = 0;
	rsc->conj = 0;
	return rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0];
	rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0];
}
}


static int srcimp_next_conj(struct rsc *rsc)
static void srcimp_next_conj(struct rsc *rsc)
{
{
	rsc->conj++;
	rsc->conj++;
	return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj];
}
}


static int srcimp_index(const struct rsc *rsc)
static int srcimp_index(const struct rsc *rsc)