]> git.pld-linux.org Git - packages/mysql.git/blame - innodb_fast_checksum.patch
- added patch for CVE-2012-2122
[packages/mysql.git] / innodb_fast_checksum.patch
CommitLineData
b4e1fa2c
AM
1# name : innodb_fast_checksum.patch
2# introduced : 11 or before
3# maintainer : Yasufumi
4#
5#!!! notice !!!
6# Any small change to this file in the main branch
7# should be done or reviewed by the maintainer!
db82db79
AM
8--- a/storage/innobase/buf/buf0buf.c
9+++ b/storage/innobase/buf/buf0buf.c
734d6226 10@@ -512,6 +512,27 @@
b4e1fa2c
AM
11 return(checksum);
12 }
13
14+UNIV_INTERN
15+ulint
16+buf_calc_page_new_checksum_32(
17+/*==========================*/
18+ const byte* page) /*!< in: buffer page */
19+{
20+ ulint checksum;
21+
22+ checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
23+ FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
24+ + ut_fold_binary(page + FIL_PAGE_DATA,
25+ FIL_PAGE_DATA_ALIGN_32 - FIL_PAGE_DATA)
26+ + ut_fold_binary_32(page + FIL_PAGE_DATA_ALIGN_32,
27+ UNIV_PAGE_SIZE - FIL_PAGE_DATA_ALIGN_32
28+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
29+
30+ checksum = checksum & 0xFFFFFFFFUL;
31+
32+ return(checksum);
33+}
34+
35 /********************************************************************//**
36 In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
37 looked at the first few bytes of the page. This calculates that old
734d6226 38@@ -628,9 +649,21 @@
b4e1fa2c
AM
39 /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
40 (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */
41
42- if (checksum_field != 0
43+ if (!srv_fast_checksum
44+ && checksum_field != 0
45+ && checksum_field != BUF_NO_CHECKSUM_MAGIC
46+ && checksum_field
47+ != buf_calc_page_new_checksum(read_buf)) {
48+
49+ return(TRUE);
50+ }
51+
52+ if (srv_fast_checksum
53+ && checksum_field != 0
54 && checksum_field != BUF_NO_CHECKSUM_MAGIC
55 && checksum_field
56+ != buf_calc_page_new_checksum_32(read_buf)
57+ && checksum_field
58 != buf_calc_page_new_checksum(read_buf)) {
59
60 return(TRUE);
734d6226 61@@ -654,6 +687,7 @@
b4e1fa2c
AM
62 dict_index_t* index;
63 #endif /* !UNIV_HOTBACKUP */
64 ulint checksum;
65+ ulint checksum_32;
66 ulint old_checksum;
67 ulint size = zip_size;
68
734d6226 69@@ -740,12 +774,14 @@
b4e1fa2c
AM
70
71 checksum = srv_use_checksums
72 ? buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
73+ checksum_32 = srv_use_checksums
74+ ? buf_calc_page_new_checksum_32(read_buf) : BUF_NO_CHECKSUM_MAGIC;
75 old_checksum = srv_use_checksums
76 ? buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
77
78 ut_print_timestamp(stderr);
79 fprintf(stderr,
80- " InnoDB: Page checksum %lu, prior-to-4.0.14-form"
81+ " InnoDB: Page checksum %lu (32bit_calc: %lu), prior-to-4.0.14-form"
82 " checksum %lu\n"
83 "InnoDB: stored checksum %lu, prior-to-4.0.14-form"
84 " stored checksum %lu\n"
734d6226 85@@ -754,7 +790,7 @@
b4e1fa2c
AM
86 "InnoDB: Page number (if stored to page already) %lu,\n"
87 "InnoDB: space id (if created with >= MySQL-4.1.1"
88 " and stored already) %lu\n",
89- (ulong) checksum, (ulong) old_checksum,
90+ (ulong) checksum, (ulong) checksum_32, (ulong) old_checksum,
91 (ulong) mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM),
92 (ulong) mach_read_from_4(read_buf + UNIV_PAGE_SIZE
93 - FIL_PAGE_END_LSN_OLD_CHKSUM),
db82db79
AM
94--- a/storage/innobase/buf/buf0flu.c
95+++ b/storage/innobase/buf/buf0flu.c
96@@ -1057,7 +1057,9 @@
b4e1fa2c
AM
97
98 mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
99 srv_use_checksums
100- ? buf_calc_page_new_checksum(page)
101+ ? (!srv_fast_checksum
102+ ? buf_calc_page_new_checksum(page)
103+ : buf_calc_page_new_checksum_32(page))
104 : BUF_NO_CHECKSUM_MAGIC);
105
106 /* We overwrite the first 4 bytes of the end lsn field to store
db82db79
AM
107--- a/storage/innobase/fil/fil0fil.c
108+++ b/storage/innobase/fil/fil0fil.c
29ffd636 109@@ -3103,13 +3103,24 @@
adf0fb13
AM
110 return(TRUE);
111 }
112
113- if (checksum_field != 0
114+ if (!srv_fast_checksum
115+ && checksum_field != 0
116 && checksum_field != BUF_NO_CHECKSUM_MAGIC
117 && checksum_field
118 != buf_calc_page_new_checksum(page)) {
119 return(TRUE);
120 }
121
122+ if (srv_fast_checksum
123+ && checksum_field != 0
124+ && checksum_field != BUF_NO_CHECKSUM_MAGIC
125+ && checksum_field
126+ != buf_calc_page_new_checksum_32(page)
127+ && checksum_field
128+ != buf_calc_page_new_checksum(page)) {
129+ return(TRUE);
130+ }
131+
132 return(FALSE);
133 }
134
29ffd636 135@@ -3125,7 +3136,9 @@
adf0fb13 136 if (!zip_size) {
b4e1fa2c
AM
137 mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
138 srv_use_checksums
139- ? buf_calc_page_new_checksum(page)
140+ ? (!srv_fast_checksum
141+ ? buf_calc_page_new_checksum(page)
142+ : buf_calc_page_new_checksum_32(page))
143 : BUF_NO_CHECKSUM_MAGIC);
144 mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
145 srv_use_checksums
db82db79
AM
146--- a/storage/innobase/handler/ha_innodb.cc
147+++ b/storage/innobase/handler/ha_innodb.cc
b4e1fa2c
AM
148@@ -183,6 +183,7 @@
149 #endif /* UNIV_LOG_ARCHIVE */
150 static my_bool innobase_use_doublewrite = TRUE;
151 static my_bool innobase_use_checksums = TRUE;
152+static my_bool innobase_fast_checksum = FALSE;
153 static my_bool innobase_recovery_stats = TRUE;
154 static my_bool innobase_locks_unsafe_for_binlog = FALSE;
155 static my_bool innobase_overwrite_relay_log_info = FALSE;
734d6226 156@@ -2656,6 +2657,7 @@
b4e1fa2c
AM
157
158 srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
159 srv_use_checksums = (ibool) innobase_use_checksums;
160+ srv_fast_checksum = (ibool) innobase_fast_checksum;
161
734d6226
AM
162 srv_blocking_lru_restore = (ibool) innobase_blocking_lru_restore;
163
29ffd636 164@@ -11541,6 +11543,15 @@
b4e1fa2c
AM
165 "Disable with --skip-innodb-checksums.",
166 NULL, NULL, TRUE);
167
168+static MYSQL_SYSVAR_BOOL(fast_checksum, innobase_fast_checksum,
169+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
170+ "Change the algorithm of checksum for the whole of datapage to 4-bytes word based. "
171+ "The original checksum is checked after the new one. It may be slow for reading page"
172+ " which has orginal checksum. Overwrite the page or recreate the InnoDB database, "
173+ "if you want the entire benefit for performance at once. "
174+ "#### Attention: The checksum is not compatible for normal or disabled version! ####",
175+ NULL, NULL, FALSE);
176+
177 static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
178 PLUGIN_VAR_READONLY,
179 "The common part for InnoDB table spaces.",
29ffd636 180@@ -12112,6 +12123,7 @@
b4e1fa2c
AM
181 MYSQL_SYSVAR(buffer_pool_size),
182 MYSQL_SYSVAR(buffer_pool_instances),
183 MYSQL_SYSVAR(checksums),
184+ MYSQL_SYSVAR(fast_checksum),
185 MYSQL_SYSVAR(commit_concurrency),
186 MYSQL_SYSVAR(concurrency_tickets),
187 MYSQL_SYSVAR(data_file_path),
db82db79
AM
188--- a/storage/innobase/include/buf0buf.h
189+++ b/storage/innobase/include/buf0buf.h
13ceb006 190@@ -621,6 +621,11 @@
b4e1fa2c
AM
191 buf_calc_page_new_checksum(
192 /*=======================*/
193 const byte* page); /*!< in: buffer page */
194+UNIV_INTERN
195+ulint
196+buf_calc_page_new_checksum_32(
197+/*==========================*/
198+ const byte* page); /*!< in: buffer page */
199 /********************************************************************//**
200 In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
201 looked at the first few bytes of the page. This calculates that old
db82db79
AM
202--- a/storage/innobase/include/fil0fil.h
203+++ b/storage/innobase/include/fil0fil.h
1bfc1981 204@@ -119,6 +119,7 @@
b4e1fa2c
AM
205 #define FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 34 /*!< starting from 4.1.x this
206 contains the space id of the page */
207 #define FIL_PAGE_DATA 38 /*!< start of the data on the page */
208+#define FIL_PAGE_DATA_ALIGN_32 40
209 /* @} */
210 /** File page trailer @{ */
211 #define FIL_PAGE_END_LSN_OLD_CHKSUM 8 /*!< the low 4 bytes of this are used
db82db79
AM
212--- a/storage/innobase/include/srv0srv.h
213+++ b/storage/innobase/include/srv0srv.h
734d6226 214@@ -229,6 +229,7 @@
b4e1fa2c
AM
215
216 extern ibool srv_use_doublewrite_buf;
217 extern ibool srv_use_checksums;
218+extern ibool srv_fast_checksum;
219
220 extern ulong srv_max_buf_pool_modified_pct;
221 extern ulong srv_max_purge_lag;
db82db79
AM
222--- a/storage/innobase/include/ut0rnd.h
223+++ b/storage/innobase/include/ut0rnd.h
b4e1fa2c
AM
224@@ -124,6 +124,13 @@
225 const byte* str, /*!< in: string of bytes */
226 ulint len) /*!< in: length */
227 __attribute__((pure));
228+UNIV_INLINE
229+ulint
230+ut_fold_binary_32(
231+/*==============*/
232+ const byte* str, /*!< in: string of bytes */
233+ ulint len) /*!< in: length */
234+ __attribute__((pure));
235 /***********************************************************//**
236 Looks for a prime number slightly greater than the given argument.
237 The prime is chosen so that it is not near any power of 2.
db82db79
AM
238--- a/storage/innobase/include/ut0rnd.ic
239+++ b/storage/innobase/include/ut0rnd.ic
b4e1fa2c
AM
240@@ -226,3 +226,28 @@
241
242 return(fold);
243 }
244+
245+UNIV_INLINE
246+ulint
247+ut_fold_binary_32(
248+/*==============*/
249+ const byte* str, /*!< in: string of bytes */
250+ ulint len) /*!< in: length */
251+{
252+ const ib_uint32_t* str_end = (const ib_uint32_t*) (str + len);
253+ const ib_uint32_t* str_32 = (const ib_uint32_t*) str;
254+ ulint fold = 0;
255+
256+ ut_ad(str);
257+ /* This function is only for word-aligned data */
258+ ut_ad(len % 4 == 0);
259+ ut_ad((ulint)str % 4 == 0);
260+
261+ while (str_32 < str_end) {
262+ fold = ut_fold_ulint_pair(fold, (ulint)(*str_32));
263+
264+ str_32++;
265+ }
266+
267+ return(fold);
268+}
db82db79
AM
269--- a/storage/innobase/srv/srv0srv.c
270+++ b/storage/innobase/srv/srv0srv.c
734d6226 271@@ -419,6 +419,7 @@
b4e1fa2c
AM
272
273 UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE;
274 UNIV_INTERN ibool srv_use_checksums = TRUE;
275+UNIV_INTERN ibool srv_fast_checksum = FALSE;
276
277 UNIV_INTERN ulong srv_replication_delay = 0;
278
13ceb006
AM
279--- /dev/null
280+++ b/mysql-test/suite/sys_vars/r/innodb_fast_checksum_basic.result
281@@ -0,0 +1,3 @@
282+SELECT @@global.innodb_fast_checksum;
283+@@global.innodb_fast_checksum
284+0
285--- /dev/null
286+++ b/mysql-test/suite/sys_vars/t/innodb_fast_checksum_basic.test
287@@ -0,0 +1 @@
288+SELECT @@global.innodb_fast_checksum;
This page took 0.154601 seconds and 4 git commands to generate.