aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorDan Carpenter <error27@gmail.com>2010-10-19 01:57:04 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-11-09 16:30:48 -0500
commitbc704e31edc723a84c2469f26aa0279e1ddb948e (patch)
tree47d9c1b9675f303be6203beb46d533af288baa26 /drivers/staging
parent3b97eed201376db6c4487fc846022eb4ffa7e1f9 (diff)
Staging: sst: more dereferencing user pointers
This is another patch about making a copy of the data into kernel space before using it. It is easy to trigger a kernel oops in the original code. If you passed a NULL to SNDRV_SST_SET_TARGET_DEVICE then it called BUG_ON(). And SNDRV_SST_DRIVER_INFO would let you write the information to arbitrary memory locations which is a security violation. Signed-off-by: Dan Carpenter <error27@gmail.com> Acked-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/intel_sst/intel_sst_app_interface.c75
1 files changed, 46 insertions, 29 deletions
diff --git a/drivers/staging/intel_sst/intel_sst_app_interface.c b/drivers/staging/intel_sst/intel_sst_app_interface.c
index a0d13ee190e5..8390aa793b7b 100644
--- a/drivers/staging/intel_sst/intel_sst_app_interface.c
+++ b/drivers/staging/intel_sst/intel_sst_app_interface.c
@@ -838,7 +838,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
838 break; 838 break;
839 839
840 case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): { 840 case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): {
841 struct snd_sst_params *str_param = (struct snd_sst_params *)arg; 841 struct snd_sst_params str_param;
842 842
843 pr_debug("sst: IOCTL_SET_PARAMS recieved!\n"); 843 pr_debug("sst: IOCTL_SET_PARAMS recieved!\n");
844 if (minor != STREAM_MODULE) { 844 if (minor != STREAM_MODULE) {
@@ -846,17 +846,25 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
846 break; 846 break;
847 } 847 }
848 848
849 if (copy_from_user(&str_param, (void __user *)arg,
850 sizeof(str_param))) {
851 retval = -EFAULT;
852 break;
853 }
854
849 if (!str_id) { 855 if (!str_id) {
850 856
851 retval = sst_get_stream(str_param); 857 retval = sst_get_stream(&str_param);
852 if (retval > 0) { 858 if (retval > 0) {
853 struct stream_info *str_info; 859 struct stream_info *str_info;
860 char __user *dest;
861
854 sst_drv_ctx->stream_cnt++; 862 sst_drv_ctx->stream_cnt++;
855 data->str_id = retval; 863 data->str_id = retval;
856 str_info = &sst_drv_ctx->streams[retval]; 864 str_info = &sst_drv_ctx->streams[retval];
857 str_info->src = SST_DRV; 865 str_info->src = SST_DRV;
858 retval = copy_to_user(&str_param->stream_id, 866 dest = (char *)arg + offsetof(struct snd_sst_params, stream_id);
859 &retval, sizeof(__u32)); 867 retval = copy_to_user(dest, &retval, sizeof(__u32));
860 if (retval) 868 if (retval)
861 retval = -EFAULT; 869 retval = -EFAULT;
862 } else { 870 } else {
@@ -866,16 +874,14 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
866 } else { 874 } else {
867 pr_debug("sst: SET_STREAM_PARAMS recieved!\n"); 875 pr_debug("sst: SET_STREAM_PARAMS recieved!\n");
868 /* allocated set params only */ 876 /* allocated set params only */
869 retval = sst_set_stream_param(str_id, str_param); 877 retval = sst_set_stream_param(str_id, &str_param);
870 /* Block the call for reply */ 878 /* Block the call for reply */
871 if (!retval) { 879 if (!retval) {
872 int sfreq = 0, word_size = 0, num_channel = 0; 880 int sfreq = 0, word_size = 0, num_channel = 0;
873 sfreq = str_param->sparams.uc.pcm_params.sfreq; 881 sfreq = str_param.sparams.uc.pcm_params.sfreq;
874 word_size = str_param->sparams. 882 word_size = str_param.sparams.uc.pcm_params.pcm_wd_sz;
875 uc.pcm_params.pcm_wd_sz; 883 num_channel = str_param.sparams.uc.pcm_params.num_chan;
876 num_channel = str_param-> 884 if (str_param.ops == STREAM_OPS_CAPTURE) {
877 sparams.uc.pcm_params.num_chan;
878 if (str_param->ops == STREAM_OPS_CAPTURE) {
879 sst_drv_ctx->scard_ops->\ 885 sst_drv_ctx->scard_ops->\
880 set_pcm_audio_params(sfreq, 886 set_pcm_audio_params(sfreq,
881 word_size, num_channel); 887 word_size, num_channel);
@@ -976,16 +982,22 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
976 } 982 }
977 983
978 case _IOC_NR(SNDRV_SST_MMAP_PLAY): 984 case _IOC_NR(SNDRV_SST_MMAP_PLAY):
979 case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): 985 case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): {
986 struct snd_sst_mmap_buffs mmap_buf;
987
980 pr_debug("sst: SNDRV_SST_MMAP_PLAY/CAPTURE recieved!\n"); 988 pr_debug("sst: SNDRV_SST_MMAP_PLAY/CAPTURE recieved!\n");
981 if (minor != STREAM_MODULE) { 989 if (minor != STREAM_MODULE) {
982 retval = -EBADRQC; 990 retval = -EBADRQC;
983 break; 991 break;
984 } 992 }
985 retval = intel_sst_mmap_play_capture(str_id, 993 if (copy_from_user(&mmap_buf, (void __user *)arg,
986 (struct snd_sst_mmap_buffs *)arg); 994 sizeof(mmap_buf))) {
995 retval = -EFAULT;
996 break;
997 }
998 retval = intel_sst_mmap_play_capture(str_id, &mmap_buf);
987 break; 999 break;
988 1000 }
989 case _IOC_NR(SNDRV_SST_STREAM_DROP): 1001 case _IOC_NR(SNDRV_SST_STREAM_DROP):
990 pr_debug("sst: SNDRV_SST_IOCTL_DROP recieved!\n"); 1002 pr_debug("sst: SNDRV_SST_IOCTL_DROP recieved!\n");
991 if (minor != STREAM_MODULE) { 1003 if (minor != STREAM_MODULE) {
@@ -996,7 +1008,6 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
996 break; 1008 break;
997 1009
998 case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): { 1010 case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): {
999 unsigned long long *ms = (unsigned long long *)arg;
1000 struct snd_sst_tstamp tstamp = {0}; 1011 struct snd_sst_tstamp tstamp = {0};
1001 unsigned long long time, freq, mod; 1012 unsigned long long time, freq, mod;
1002 1013
@@ -1013,7 +1024,8 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
1013 freq = (unsigned long long) tstamp.sampling_frequency; 1024 freq = (unsigned long long) tstamp.sampling_frequency;
1014 time = time * 1000; /* converting it to ms */ 1025 time = time * 1000; /* converting it to ms */
1015 mod = do_div(time, freq); 1026 mod = do_div(time, freq);
1016 if (copy_to_user(ms, &time, sizeof(*ms))) 1027 if (copy_to_user((void __user *)arg, &time,
1028 sizeof(unsigned long long)))
1017 retval = -EFAULT; 1029 retval = -EFAULT;
1018 break; 1030 break;
1019 } 1031 }
@@ -1058,32 +1070,37 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg)
1058 } 1070 }
1059 1071
1060 case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): { 1072 case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): {
1061 struct snd_sst_target_device *target_device; 1073 struct snd_sst_target_device target_device;
1062 1074
1063 pr_debug("sst: SET_TARGET_DEVICE recieved!\n"); 1075 pr_debug("sst: SET_TARGET_DEVICE recieved!\n");
1064 target_device = (struct snd_sst_target_device *)arg; 1076 if (copy_from_user(&target_device, (void __user *)arg,
1065 BUG_ON(!target_device); 1077 sizeof(target_device))) {
1078 retval = -EFAULT;
1079 break;
1080 }
1066 if (minor != AM_MODULE) { 1081 if (minor != AM_MODULE) {
1067 retval = -EBADRQC; 1082 retval = -EBADRQC;
1068 break; 1083 break;
1069 } 1084 }
1070 retval = sst_target_device_select(target_device); 1085 retval = sst_target_device_select(&target_device);
1071 break; 1086 break;
1072 } 1087 }
1073 1088
1074 case _IOC_NR(SNDRV_SST_DRIVER_INFO): { 1089 case _IOC_NR(SNDRV_SST_DRIVER_INFO): {
1075 struct snd_sst_driver_info *info = 1090 struct snd_sst_driver_info info;
1076 (struct snd_sst_driver_info *)arg;
1077 1091
1078 pr_debug("sst: SNDRV_SST_DRIVER_INFO recived\n"); 1092 pr_debug("sst: SNDRV_SST_DRIVER_INFO recived\n");
1079 info->version = SST_VERSION_NUM; 1093 info.version = SST_VERSION_NUM;
1080 /* hard coding, shud get sumhow later */ 1094 /* hard coding, shud get sumhow later */
1081 info->active_pcm_streams = sst_drv_ctx->stream_cnt - 1095 info.active_pcm_streams = sst_drv_ctx->stream_cnt -
1082 sst_drv_ctx->encoded_cnt; 1096 sst_drv_ctx->encoded_cnt;
1083 info->active_enc_streams = sst_drv_ctx->encoded_cnt; 1097 info.active_enc_streams = sst_drv_ctx->encoded_cnt;
1084 info->max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM; 1098 info.max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM;
1085 info->max_enc_streams = MAX_ENC_STREAM; 1099 info.max_enc_streams = MAX_ENC_STREAM;
1086 info->buf_per_stream = sst_drv_ctx->mmap_len; 1100 info.buf_per_stream = sst_drv_ctx->mmap_len;
1101 if (copy_to_user((void __user *)arg, &info,
1102 sizeof(info)))
1103 retval = -EFAULT;
1087 break; 1104 break;
1088 } 1105 }
1089 1106