ALSA: Avoid using timespec for struct snd_pcm_status
The struct snd_pcm_status will use 'timespec' type variables to record
timestamp, which is not year 2038 safe on 32bits system.
Userspace will use SNDRV_PCM_IOCTL_STATUS and SNDRV_PCM_IOCTL_STATUS_EXT
as commands to issue ioctl() to fill the 'snd_pcm_status' structure in
userspace. The command number is always defined through _IOR/_IOW/IORW,
so when userspace changes the definition of 'struct timespec' to use
64-bit types, the command number also changes.
Thus in the kernel, we now need to define two versions of each such ioctl
and corresponding ioctl commands to handle 32bit time_t and 64bit time_t
in native mode:
struct snd_pcm_status32 {
......
s32 trigger_tstamp_sec;
s32 trigger_tstamp_nsec;
......
s32 audio_tstamp_sec;
s32 audio_tstamp_nsec;
......
};
struct snd_pcm_status64 {
......
s32 trigger_tstamp_sec;
s32 trigger_tstamp_nsec;
......
s32 audio_tstamp_sec;
s32 audio_tstamp_nsec;
......
};
Moreover in compat file, we renamed or introduced new structures to handle
32bit/64bit time_t in compatible mode. The 'struct snd_pcm_status32' and
snd_pcm_status_user32() are used to handle 32bit time_t in compat mode.
'struct compat_snd_pcm_status64' and snd_pcm_status_user_compat64() are used
to handle 64bit time_t.
The implicit padding before timespec is made explicit to avoid incompatible
structure layout between 32-bit and 64-bit x86 due to the different
alignment requirements, and the snd_pcm_status structure is now hidden
from the kernel to avoid relying on the timespec definitio definitionn
Finally we can replace SNDRV_PCM_IOCTL_STATUS and SNDRV_PCM_IOCTL_STATUS_EXT
with new commands and introduce new functions to fill new 'struct snd_pcm_status64'
instead of using unsafe 'struct snd_pcm_status'. Then in future, the new
commands can be matched when userspace changes 'timespec' to 64bit type
to make a size change of 'struct snd_pcm_status'. When glibc changes time_t
to 64-bit, any recompiled program will issue ioctl commands that the kernel
does not understand without this patch.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 9a72d64..85db55e 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -443,7 +443,7 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
{
struct snd_pcm_substream *substream = entry->private_data;
struct snd_pcm_runtime *runtime;
- struct snd_pcm_status status;
+ struct snd_pcm_status64 status;
int err;
mutex_lock(&substream->pcm->open_mutex);
@@ -453,17 +453,17 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
goto unlock;
}
memset(&status, 0, sizeof(status));
- err = snd_pcm_status(substream, &status);
+ err = snd_pcm_status64(substream, &status);
if (err < 0) {
snd_iprintf(buffer, "error %d\n", err);
goto unlock;
}
snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid));
- snd_iprintf(buffer, "trigger_time: %ld.%09ld\n",
- status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec);
- snd_iprintf(buffer, "tstamp : %ld.%09ld\n",
- status.tstamp.tv_sec, status.tstamp.tv_nsec);
+ snd_iprintf(buffer, "trigger_time: %lld.%09lld\n",
+ status.trigger_tstamp_sec, status.trigger_tstamp_nsec);
+ snd_iprintf(buffer, "tstamp : %lld.%09lld\n",
+ status.tstamp_sec, status.tstamp_nsec);
snd_iprintf(buffer, "delay : %ld\n", status.delay);
snd_iprintf(buffer, "avail : %ld\n", status.avail);
snd_iprintf(buffer, "avail_max : %ld\n", status.avail_max);