| From 463b6181750ca755f9c6e1ebcfb864f483bee75d Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 13 Feb 2024 14:53:43 +0100 |
| Subject: ALSA: seq: fix function cast warnings |
| |
| From: Takashi Iwai <tiwai@suse.de> |
| |
| [ Upstream commit d7bf73809849463f76de42aad62c850305dd6c5d ] |
| |
| clang-16 points out a control flow integrity (kcfi) issue when event |
| callbacks get converted to incompatible types: |
| |
| sound/core/seq/seq_midi.c:135:30: error: cast from 'int (*)(struct snd_rawmidi_substream *, const char *, int)' to 'snd_seq_dump_func_t' (aka 'int (*)(void *, void *, int)') converts to incompatible function type [-Werror,-Wcast-function-type-strict] |
| 135 | snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream); |
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| sound/core/seq/seq_virmidi.c:83:31: error: cast from 'int (*)(struct snd_rawmidi_substream *, const unsigned char *, int)' to 'snd_seq_dump_func_t' (aka 'int (*)(void *, void *, int)') converts to incompatible function type [-Werror,-Wcast-function-type-strict] |
| 83 | snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)snd_rawmidi_receive, vmidi->substream); |
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| For addressing those errors, introduce wrapper functions that are used |
| for callbacks and bridge to the actual function call with pointer |
| cast. |
| |
| The code was originally added with the initial ALSA merge in linux-2.5.4. |
| |
| [ the patch description shamelessly copied from Arnd's original patch |
| -- tiwai ] |
| |
| Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") |
| Reported-by: Arnd Bergmann <arnd@arndb.de> |
| Link: https://lore.kernel.org/r/20240213101020.459183-1-arnd@kernel.org |
| Link: https://lore.kernel.org/r/20240213135343.16411-1-tiwai@suse.de |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| sound/core/seq/seq_midi.c | 8 +++++++- |
| sound/core/seq/seq_virmidi.c | 9 ++++++++- |
| 2 files changed, 15 insertions(+), 2 deletions(-) |
| |
| diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c |
| index 18320a248aa7d..78dcb0ea15582 100644 |
| --- a/sound/core/seq/seq_midi.c |
| +++ b/sound/core/seq/seq_midi.c |
| @@ -113,6 +113,12 @@ static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, i |
| return 0; |
| } |
| |
| +/* callback for snd_seq_dump_var_event(), bridging to dump_midi() */ |
| +static int __dump_midi(void *ptr, void *buf, int count) |
| +{ |
| + return dump_midi(ptr, buf, count); |
| +} |
| + |
| static int event_process_midi(struct snd_seq_event *ev, int direct, |
| void *private_data, int atomic, int hop) |
| { |
| @@ -132,7 +138,7 @@ static int event_process_midi(struct snd_seq_event *ev, int direct, |
| pr_debug("ALSA: seq_midi: invalid sysex event flags = 0x%x\n", ev->flags); |
| return 0; |
| } |
| - snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream); |
| + snd_seq_dump_var_event(ev, __dump_midi, substream); |
| snd_midi_event_reset_decode(msynth->parser); |
| } else { |
| if (msynth->parser == NULL) |
| diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c |
| index 1b9260108e482..1678737f11be7 100644 |
| --- a/sound/core/seq/seq_virmidi.c |
| +++ b/sound/core/seq/seq_virmidi.c |
| @@ -62,6 +62,13 @@ static void snd_virmidi_init_event(struct snd_virmidi *vmidi, |
| /* |
| * decode input event and put to read buffer of each opened file |
| */ |
| + |
| +/* callback for snd_seq_dump_var_event(), bridging to snd_rawmidi_receive() */ |
| +static int dump_to_rawmidi(void *ptr, void *buf, int count) |
| +{ |
| + return snd_rawmidi_receive(ptr, buf, count); |
| +} |
| + |
| static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, |
| struct snd_seq_event *ev, |
| bool atomic) |
| @@ -80,7 +87,7 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, |
| if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { |
| if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) |
| continue; |
| - snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)snd_rawmidi_receive, vmidi->substream); |
| + snd_seq_dump_var_event(ev, dump_to_rawmidi, vmidi->substream); |
| snd_midi_event_reset_decode(vmidi->parser); |
| } else { |
| len = snd_midi_event_decode(vmidi->parser, msg, sizeof(msg), ev); |
| -- |
| 2.43.0 |
| |