已开启
fix vulnerability and enhance security #169
fix vulnerability and enhance security #169
已开启
asdfghjklz23432创建于 7月15日
2 个文件变更+765-1
@@ -0,0 +1,759 @@
1+diff -uNr nss/cmd/modutil/install.c nss-new/cmd/modutil/install.c
2+--- nss/cmd/modutil/install.c 2023-10-02 20:17:27.000000000 +0800
3++++ nss-new/cmd/modutil/install.c 2026-07-08 16:11:40.470218903 +0800
4+@@ -797,7 +797,8 @@
5+ PRDir *dir;
6+ PRDirEntry *entry;
7+ PRFileInfo fileinfo;
8+- char filename[240];
9++ char *filename;
10++ size_t pathLen, nameLen;
11+
12+ if (PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
13+ /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/
14+@@ -812,11 +813,21 @@
15+
16+ /* Recursively delete all entries in the directory */
17+ while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
18+- snprintf(filename, sizeof(filename), "%s/%s", path, entry->name);
19++ pathLen = strlen(path);
20++ nameLen = strlen(entry->name);
21++ /* +2 for '/' and terminating NUL */
22++ filename = (char *)PR_Malloc(pathLen + nameLen + 2);
23++ if (!filename) {
24++ PR_CloseDir(dir);
25++ return -1;
26++ }
27++ snprintf(filename, pathLen + nameLen + 2, "%s/%s", path, entry->name);
28+ if (rm_dash_r(filename)) {
29++ PR_Free(filename);
30+ PR_CloseDir(dir);
31+ return -1;
32+ }
33++ PR_Free(filename);
34+ }
35+
36+ if (PR_CloseDir(dir) != PR_SUCCESS) {
37+diff -uNr nss/cmd/signtool/javascript.c nss-new/cmd/signtool/javascript.c
38+--- nss/cmd/signtool/javascript.c 2023-10-02 20:17:27.000000000 +0800
39++++ nss-new/cmd/signtool/javascript.c 2026-07-08 16:11:40.470218903 +0800
40+@@ -6,6 +6,7 @@
41+ #include <prmem.h>
42+ #include <prio.h>
43+ #include <prenv.h>
44++#include <sys/stat.h>
45+
46+ static int javascript_fn(char *relpath, char *basedir, char *reldir,
47+ char *filename, void *arg);
48+@@ -877,21 +878,41 @@
49+
50+ filename = PR_smprintf("%s/%s/%s", basedir, ilDir, id);
51+
52+- /* If the file already exists, give a warning, then blow it away */
53+- if (PR_Access(filename, PR_ACCESS_EXISTS) == PR_SUCCESS) {
54+- PR_fprintf(errorFD,
55+- "warning: file \"%s\" already exists--will overwrite.\n",
56+- filename);
57+- warningCount++;
58+- if (rm_dash_r(filename)) {
59+- PR_fprintf(errorFD, "ERROR: Unable to delete %s.\n", filename);
60+- errorCount++;
61+- goto finish;
62++ /* Use lstat to detect symlinks without following them, preventing
63++ TOCTOU symlink attacks between check and open. */
64++ {
65++ struct stat st;
66++ if (lstat(filename, &st) == 0) {
67++ if (S_ISLNK(st.st_mode)) {
68++ PR_fprintf(errorFD,
69++ "ERROR: refusing to follow symlink at \"%s\".\n",
70++ filename);
71++ errorCount++;
72++ goto finish;
73++ }
74++ if (S_ISDIR(st.st_mode)) {
75++ PR_fprintf(errorFD,
76++ "warning: directory \"%s\" already exists--will overwrite.\n",
77++ filename);
78++ warningCount++;
79++ if (rm_dash_r(filename)) {
80++ PR_fprintf(errorFD, "ERROR: Unable to delete %s.\n", filename);
81++ errorCount++;
82++ goto finish;
83++ }
84++ } else {
85++ PR_fprintf(errorFD,
86++ "warning: file \"%s\" already exists--will overwrite.\n",
87++ filename);
88++ warningCount++;
89++ }
90+ }
91+ }
92+
93+- /* Write text into file with name id */
94+- fd = PR_Open(filename, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0777);
95++ /* Write text into file with name id.
96++ PR_TRUNCATE atomically overwrites regular files without a separate
97++ delete step, closing the TOCTOU window. */
98++ fd = PR_Open(filename, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600);
99+ if (!fd) {
100+ PR_fprintf(errorFD, "ERROR: Unable to create file \"%s\".\n",
101+ filename);
102+@@ -1770,19 +1791,37 @@
103+ goto finish;
104+ }
105+
106+- /* If to already exists, print a warning before deleting it */
107+- if (PR_Access(to, PR_ACCESS_EXISTS) == PR_SUCCESS) {
108+- PR_fprintf(errorFD, "warning: %s already exists--will overwrite\n", to);
109+- warningCount++;
110+- if (rm_dash_r(to)) {
111+- PR_fprintf(errorFD,
112+- "ERROR: Unable to remove %s.\n", to);
113+- errorCount++;
114+- goto finish;
115++ /* Use lstat to detect symlinks without following them, preventing
116++ TOCTOU symlink attacks between check and open */
117++ {
118++ struct stat st;
119++ if (lstat(to, &st) == 0) {
120++ if (S_ISLNK(st.st_mode)) {
121++ PR_fprintf(errorFD,
122++ "ERROR: refusing to follow symlink at \"%s\".\n",
123++ to);
124++ errorCount++;
125++ goto finish;
126++ }
127++ if (S_ISDIR(st.st_mode)) {
128++ PR_fprintf(errorFD,
129++ "warning: %s is a directory--will overwrite\n", to);
130++ warningCount++;
131++ if (rm_dash_r(to)) {
132++ PR_fprintf(errorFD,
133++ "ERROR: Unable to remove %s.\n", to);
134++ errorCount++;
135++ goto finish;
136++ }
137++ } else {
138++ PR_fprintf(errorFD,
139++ "warning: %s already exists--will overwrite\n", to);
140++ warningCount++;
141++ }
142+ }
143+ }
144+
145+- if ((outfp = PR_Open(to, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0777)) ==
146++ if ((outfp = PR_Open(to, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600)) ==
147+ NULL) {
148+ char *errBuf = NULL;
149+
150+diff -uNr nss/cmd/signtool/sign.c nss-new/cmd/signtool/sign.c
151+--- nss/cmd/signtool/sign.c 2023-10-02 20:17:27.000000000 +0800
152++++ nss-new/cmd/signtool/sign.c 2026-07-08 16:11:40.470218903 +0800
153+@@ -368,14 +368,19 @@
154+ exit(ERRX);
155+ }
156+
157+- snprintf(metadir, sizeof(metadir), "%s/META-INF", dirname);
158+-
159+- strcpy(sfname, metadir);
160++ if (snprintf(metadir, sizeof(metadir), "%s/META-INF", dirname) >= sizeof(metadir)) {
161++ PR_fprintf(errorFD, "%s: directory path too long: %s\n", PROGRAM_NAME, dirname);
162++ errorCount++;
163++ return -1;
164++ }
165+
166+ PR_MkDir(metadir, 0777);
167+
168+- strcat(metadir, "/");
169+- strcat(metadir, MANIFEST);
170++ if (snprintf(metadir, sizeof(metadir), "%s/META-INF/%s", dirname, MANIFEST) >= sizeof(metadir)) {
171++ PR_fprintf(errorFD, "%s: manifest path too long: %s\n", PROGRAM_NAME, dirname);
172++ errorCount++;
173++ return -1;
174++ }
175+
176+ if ((mf = fopen(metadir, "wb")) == NULL) {
177+ perror(MANIFEST);
178+@@ -418,9 +423,11 @@
179+
180+ fclose(mf);
181+
182+- strcat(sfname, "/");
183+- strcat(sfname, base);
184+- strcat(sfname, ".sf");
185++ if (snprintf(sfname, sizeof(sfname), "%s/META-INF/%s.sf", dirname, base) >= sizeof(sfname)) {
186++ PR_fprintf(errorFD, "%s: path too long for %s/META-INF/%s.sf\n", PROGRAM_NAME, dirname, base);
187++ errorCount++;
188++ return -1;
189++ }
190+
191+ if (verbosity >= 0) {
192+ PR_fprintf(outputFD, "Generating %s.sf file..\n", base);
193+@@ -716,7 +723,11 @@
194+ JAR_Digest dig;
195+ int line = 0;
196+
197+- strcpy(whofile, who);
198++ if (snprintf(whofile, sizeof(whofile), "%s", who) >= sizeof(whofile)) {
199++ PR_fprintf(errorFD, "%s: SF file path too long\n", PROGRAM_NAME);
200++ errorCount++;
201++ return -1;
202++ }
203+
204+ if ((mfFile = fopen(manifile, "rb")) == NULL) {
205+ perror(manifile);
206+diff -uNr nss/cmd/signtool/signtool.c nss-new/cmd/signtool/signtool.c
207+--- nss/cmd/signtool/signtool.c 2023-10-02 20:17:27.000000000 +0800
208++++ nss-new/cmd/signtool/signtool.c 2026-07-08 16:11:40.470218903 +0800
209+@@ -17,6 +17,7 @@
210+ #include "signtool.h"
211+ #include "prmem.h"
212+ #include "prio.h"
213++#include <sys/stat.h>
214+
215+ /***********************************************************************
216+ * Global Variable Definitions
217+@@ -857,22 +858,27 @@
218+
219+ /* Set up output redirection */
220+ if (outfile) {
221+- if (PR_Access(outfile, PR_ACCESS_EXISTS) == PR_SUCCESS) {
222+- /* delete the file if it is already present */
223++ /* Use lstat to detect symlinks without following them, preventing
224++ TOCTOU symlink attacks between check and open */
225++ struct stat st;
226++ if (lstat(outfile, &st) == 0) {
227++ if (S_ISLNK(st.st_mode)) {
228++ PR_fprintf(errorFD,
229++ "ERROR: refusing to follow symlink at \"%s\".\n",
230++ outfile);
231++ errorCount++;
232++ exit(ERRX);
233++ }
234+ PR_fprintf(errorFD,
235+ "warning: %s already exists and will be overwritten.\n",
236+ outfile);
237+ warningCount++;
238+- if (PR_Delete(outfile) != PR_SUCCESS) {
239+- PR_fprintf(errorFD, "ERROR: unable to delete %s.\n", outfile);
240+- errorCount++;
241+- exit(ERRX);
242+- }
243+ }
244++
245+ outputFD = PR_Open(outfile,
246+ PR_WRONLY |
247+ PR_CREATE_FILE | PR_TRUNCATE,
248+- 0777);
249++ 0600);
250+ if (!outputFD) {
251+ PR_fprintf(errorFD, "ERROR: Unable to create %s.\n",
252+ outfile);
253+diff -uNr nss/cmd/signtool/util.c nss-new/cmd/signtool/util.c
254+--- nss/cmd/signtool/util.c 2023-10-02 20:17:27.000000000 +0800
255++++ nss-new/cmd/signtool/util.c 2026-07-08 16:11:40.471218908 +0800
256+@@ -457,10 +457,9 @@
257+ PRDir *dir;
258+ PRDirEntry *entry;
259+
260+- strcpy(newdir, dirname);
261+- if (*prefix) {
262+- strcat(newdir, "/");
263+- strcat(newdir, prefix);
264++ if (PR_snprintf(newdir, FNSIZE, "%s%s%s",
265++ dirname, *prefix ? "/" : "", prefix) >= FNSIZE) {
266++ return -1;
267+ }
268+
269+ dir = PR_OpenDir(newdir);
270+@@ -482,23 +481,23 @@
271+ if (PL_HashTableLookup(excludeDirs, entry->name))
272+ continue;
273+
274+- strcpy(newdir, dirname);
275+- if (*dirname)
276+- strcat(newdir, "/");
277+-
278+- if (*prefix) {
279+- strcat(newdir, prefix);
280+- strcat(newdir, "/");
281++ if (PR_snprintf(newdir, FNSIZE, "%s%s%s%s%s",
282++ dirname, *dirname ? "/" : "",
283++ prefix, *prefix ? "/" : "",
284++ entry->name) >= FNSIZE) {
285++ PR_CloseDir(dir);
286++ return -1;
287+ }
288+- strcat(newdir, entry->name);
289+
290+ if (!is_dir(newdir) || includeDirs) {
291+ char newpath[FNSIZE];
292+
293+- strcpy(newpath, prefix);
294+- if (*newpath)
295+- strcat(newpath, "/");
296+- strcat(newpath, entry->name);
297++ if (PR_snprintf(newpath, FNSIZE, "%s%s%s",
298++ prefix, *prefix ? "/" : "",
299++ entry->name) >= FNSIZE) {
300++ PR_CloseDir(dir);
301++ return -1;
302++ }
303+
304+ if ((*fn)(newpath, dirname, prefix, (char *)entry->name,
305+ arg)) {
306+@@ -511,11 +510,12 @@
307+ if (recurse) {
308+ char newprefix[FNSIZE];
309+
310+- strcpy(newprefix, prefix);
311+- if (*newprefix) {
312+- strcat(newprefix, "/");
313++ if (PR_snprintf(newprefix, FNSIZE, "%s%s%s",
314++ prefix, *prefix ? "/" : "",
315++ entry->name) >= FNSIZE) {
316++ PR_CloseDir(dir);
317++ return -1;
318+ }
319+- strcat(newprefix, entry->name);
320+
321+ if (foreach (dirname, newprefix, fn, recurse,
322+ includeDirs, arg)) {
323+diff -uNr nss/cmd/signtool/verify.c nss-new/cmd/signtool/verify.c
324+--- nss/cmd/signtool/verify.c 2023-10-02 20:17:27.000000000 +0800
325++++ nss-new/cmd/signtool/verify.c 2026-07-08 16:11:40.471218908 +0800
326+@@ -3,6 +3,7 @@
327+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
328+
329+ #include "signtool.h"
330++#include <sys/stat.h>
331+
332+ static int jar_cb(int status, JAR *jar, const char *metafile,
333+ char *pathname, char *errortext);
334+@@ -15,8 +16,6 @@
335+ int
336+ VerifyJar(char *filename)
337+ {
338+- FILE *fp;
339+-
340+ int ret;
341+ int status;
342+ int failed = 0;
343+@@ -29,11 +28,22 @@
344+
345+ jar = JAR_new();
346+
347+- if ((fp = fopen(filename, "r")) == NULL) {
348+- perror(filename);
349+- exit(ERRX);
350+- } else
351+- fclose(fp);
352++ /* Reject symlinks to prevent TOCTOU symlink attacks:
353++ a previous fopen/fclose check followed by JAR_pass_archive
354++ left a window where the file could be swapped. */
355++ {
356++ struct stat st;
357++ if (lstat(filename, &st) != 0) {
358++ perror(filename);
359++ exit(ERRX);
360++ }
361++ if (S_ISLNK(st.st_mode)) {
362++ PR_fprintf(outputFD,
363++ "ERROR: refusing to follow symlink at \"%s\".\n",
364++ filename);
365++ exit(ERRX);
366++ }
367++ }
368+
369+ JAR_set_callback(JAR_CB_SIGNAL, jar, jar_cb);
370+
371+diff -uNr nss/lib/cryptohi/secsign.c nss-new/lib/cryptohi/secsign.c
372+--- nss/lib/cryptohi/secsign.c 2026-07-08 16:13:41.067804018 +0800
373++++ nss-new/lib/cryptohi/secsign.c 2026-07-08 16:11:40.471218908 +0800
374+@@ -907,7 +907,7 @@
375+ unsigned int len;
376+ PK11Context *ctx;
377+
378+- if (!z || !pub || pub->len != 65)
379++ if (!z || !pub || !pub->data || pub->len != 65)
380+ return SECFailure;
381+
382+ ctx = PK11_CreateDigestContext(SEC_OID_SM3);
383+diff -uNr nss/lib/freebl/ecl/ecl-curve.h nss-new/lib/freebl/ecl/ecl-curve.h
384+--- nss/lib/freebl/ecl/ecl-curve.h 2026-07-08 16:13:41.067804018 +0800
385++++ nss-new/lib/freebl/ecl/ecl-curve.h 2026-07-08 16:11:40.471218908 +0800
386+@@ -206,8 +206,8 @@
387+ static const ECCurveBytes ecCurve_sm2p256v1 = {
388+ "sm2p256v1", ECField_GFp, 256,
389+ sm2_irr, sm2_a, sm2_b, sm2_x, sm2_y, sm2_order, NULL,
390+- 8, 128, 66, 32, // TODO
391+- KU_KEY_AGREEMENT
392++ 8, 128, 66, 32,
393++ KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
394+ };
395+
396+ /* mapping between ECCurveName enum and pointers to ECCurveParams */
397+diff -uNr nss/lib/freebl/sm2.c nss-new/lib/freebl/sm2.c
398+--- nss/lib/freebl/sm2.c 2026-07-08 16:13:41.061803989 +0800
399++++ nss-new/lib/freebl/sm2.c 2026-07-08 16:14:32.655054318 +0800
400+@@ -22,7 +22,7 @@
401+ mp_int e, k, x1, y1, r, n, dA, tmp, s;
402+ mp_err err = MP_OKAY;
403+ ECParams *ecParams;
404+- ECGroup *group;
405++ ECGroup *group = NULL;
406+ SECItem kGpoint = { siBuffer, NULL, 0 };
407+ mp_size olen;
408+
409+@@ -47,8 +47,6 @@
410+ CHECK_MPI_OK(mp_init(&dA));
411+ CHECK_MPI_OK(mp_init(&tmp));
412+ CHECK_MPI_OK(mp_init(&s));
413+- CHECK_MPI_OK(mp_init(&tmp));
414+- CHECK_MPI_OK(mp_init(&s));
415+
416+ SECITEM_TO_MPINT(key->privateValue, &dA);
417+ SECITEM_TO_MPINT(*digest, &e);
418+@@ -67,6 +65,7 @@
419+ if (!group)
420+ goto cleanup;
421+
422++
423+ kGpoint.len = EC_GetPointSize(ecParams);
424+ kGpoint.data = PORT_Alloc(kGpoint.len);
425+ if (kGpoint.data == NULL)
426+@@ -125,6 +124,12 @@
427+ if (kGpoint.data)
428+ PORT_ZFree(kGpoint.data, kGpoint.len);
429+
430++ ECGroup_free(group);
431++
432++ /* SM2 signature uses large stack variables to store intermediate results,
433++ * clear our stack before returning to prevent CSP leakage */
434++ BLAPI_CLEAR_STACK(2048)
435++
436+ if (err) {
437+ MP_TO_SEC_ERROR(err);
438+ rv = SECFailure;
439+diff -uNr nss/lib/freebl/sm3.c nss-new/lib/freebl/sm3.c
440+--- nss/lib/freebl/sm3.c 2026-07-08 16:13:41.060803984 +0800
441++++ nss-new/lib/freebl/sm3.c 2026-07-08 16:11:40.471218908 +0800
442+@@ -119,6 +119,9 @@
443+ void
444+ SM3_DestroyContext(SM3Context *ctx, PRBool freeit)
445+ {
446++ if (ctx == NULL) {
447++ return;
448++ }
449+ memset(ctx, 0, sizeof *ctx);
450+ if (freeit) {
451+ PORT_Free(ctx);
452+@@ -128,6 +131,9 @@
453+ void
454+ SM3_Begin(SM3Context *ctx)
455+ {
456++ if (ctx == NULL) {
457++ return;
458++ }
459+ memset(ctx, 0, sizeof(SM3Context));
460+ ctx->A = 0x7380166fUL;
461+ ctx->B = 0x4914b2b9UL;
462+@@ -143,6 +149,9 @@
463+ SM3_Update(SM3Context *ctx, const unsigned char *input,
464+ unsigned int inputLen)
465+ {
466++ if (ctx == NULL) {
467++ return;
468++ }
469+ PRUint32 l, n, rest;
470+ PRUint8 *p;
471+
472+@@ -187,6 +196,9 @@
473+ SM3_End(SM3Context *ctx, unsigned char *digest,
474+ unsigned int *digestLen, unsigned int maxDigestLen)
475+ {
476++ if (ctx == NULL || digest == NULL) {
477++ return;
478++ }
479+ PRUint32 n = ctx->num;
480+
481+ if (maxDigestLen < SM3_LENGTH) {
482+@@ -226,6 +238,11 @@
483+ SM3Context ctx;
484+ unsigned int outLen;
485+
486++ if (dest == NULL || (src == NULL && src_length != 0)) {
487++ PORT_SetError(SEC_ERROR_INVALID_ARGS);
488++ return SECFailure;
489++ }
490++
491+ SM3_Begin(&ctx);
492+ SM3_Update(&ctx, src, src_length);
493+ SM3_End(&ctx, dest, &outLen, SM3_LENGTH);
494+@@ -248,12 +265,19 @@
495+ unsigned int
496+ SM3_FlattenSize(SM3Context *ctx)
497+ {
498++ if (ctx == NULL) {
499++ return 0;
500++ }
501+ return sizeof *ctx;
502+ }
503+
504+ SECStatus
505+ SM3_Flatten(SM3Context *ctx, unsigned char *space)
506+ {
507++ if (ctx == NULL || space == NULL) {
508++ PORT_SetError(SEC_ERROR_INVALID_ARGS);
509++ return SECFailure;
510++ }
511+ PORT_Memcpy(space, ctx, sizeof *ctx);
512+ return SECSuccess;
513+ }
514+diff -uNr nss/lib/pkcs12/p12d.c nss-new/lib/pkcs12/p12d.c
515+--- nss/lib/pkcs12/p12d.c 2026-07-08 16:13:41.074804052 +0800
516++++ nss-new/lib/pkcs12/p12d.c 2026-07-08 16:11:40.471218908 +0800
517+@@ -1125,28 +1125,44 @@
518+ p12u_DigestWrite(void *arg, unsigned char *buf, unsigned long len)
519+ {
520+ SEC_PKCS12DecoderContext *p12cxt = arg;
521++ size_t required;
522++ size_t newsize;
523+
524+ if (!buf || len == 0) {
525+ return -1;
526+ }
527+
528+ if (p12cxt->currentpos + (long)len > p12cxt->filesize) {
529+- p12cxt->filesize = p12cxt->currentpos + len;
530++ required = p12cxt->currentpos + len;
531+ } else {
532+- p12cxt->filesize += len;
533++ required = p12cxt->filesize + len;
534+ }
535+- if (p12cxt->filesize > p12cxt->allocated) {
536++
537++ /* Validate we can safely store the new size in a PRInt32, and avoid
538++ integer overflow when computing sizes. */
539++ if (required > PR_INT32_MAX) {
540++ PORT_SetError(SEC_ERROR_INPUT_LEN);
541++ return -1;
542++ }
543++
544++ if (required > (size_t)p12cxt->allocated) {
545+ void *newbuffer;
546+- size_t newsize = p12cxt->filesize + DEFAULT_TEMP_SIZE;
547++ if (required > PR_INT32_MAX - DEFAULT_TEMP_SIZE) {
548++ PORT_SetError(SEC_ERROR_INPUT_LEN);
549++ return -1;
550++ }
551++ newsize = required + DEFAULT_TEMP_SIZE;
552+ newbuffer = PORT_Realloc(p12cxt->buffer, newsize);
553+ if (NULL == newbuffer) {
554+ return -1; /* can't extend the buffer */
555+ }
556+ p12cxt->buffer = newbuffer;
557+- p12cxt->allocated = newsize;
558++ p12cxt->allocated = (PRInt32)newsize;
559+ }
560++
561+ PR_ASSERT(p12cxt->buffer);
562+ memcpy((char *)p12cxt->buffer + p12cxt->currentpos, buf, len);
563++ p12cxt->filesize = (PRInt32)required;
564+ p12cxt->currentpos += len;
565+ return len;
566+ }
567+diff -uNr nss/lib/pkcs12/p12local.c nss-new/lib/pkcs12/p12local.c
568+--- nss/lib/pkcs12/p12local.c 2023-10-02 20:17:27.000000000 +0800
569++++ nss-new/lib/pkcs12/p12local.c 2026-07-08 16:11:40.472218913 +0800
570+@@ -3,6 +3,7 @@
571+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
572+
573+ #include "nssrenam.h"
574++#include <limits.h>
575+ #include "pkcs12.h"
576+ #include "secpkcs7.h"
577+ #include "secasn1.h"
578+@@ -553,6 +554,7 @@
579+ PRBool swap)
580+ {
581+ SECItem uniPwd = { siBuffer, NULL, 0 }, *retPwd = NULL;
582++ unsigned int allocLen;
583+
584+ if ((password == NULL) || (salt == NULL)) {
585+ return NULL;
586+@@ -565,8 +567,16 @@
587+ return NULL;
588+ }
589+ } else {
590+- uniPwd.data = (unsigned char *)PORT_ZAlloc(password->len * 3);
591+- uniPwd.len = password->len * 3;
592++ /* The output of PORT_UCS2_ASCIIConversion is at most 3 bytes per
593++ * input byte. Reject inputs that would overflow the unsigned int
594++ * length used by SECItem and PORT_Alloc. */
595++ if (password->len > UINT_MAX / 3) {
596++ PORT_SetError(SEC_ERROR_INPUT_LEN);
597++ return NULL;
598++ }
599++ allocLen = password->len * 3;
600++ uniPwd.data = (unsigned char *)PORT_ZAlloc(allocLen);
601++ uniPwd.len = allocLen;
602+ if (!PORT_UCS2_ASCIIConversion(PR_TRUE, password->data, password->len,
603+ uniPwd.data, uniPwd.len, &uniPwd.len, swap)) {
604+ SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
605+@@ -574,6 +584,15 @@
606+ }
607+ }
608+
609++ /* uniPwd.len has been reduced to the actual converted length by
610++ * PORT_UCS2_ASCIIConversion, so it is no larger than the original
611++ * allocation. Reject the sum with salt->len if it would overflow. */
612++ if (UINT_MAX - uniPwd.len < salt->len) {
613++ SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
614++ PORT_SetError(SEC_ERROR_INPUT_LEN);
615++ return NULL;
616++ }
617++
618+ retPwd = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
619+ if (retPwd == NULL) {
620+ goto loser;
621+diff -uNr nss/lib/util/derdec.c nss-new/lib/util/derdec.c
622+--- nss/lib/util/derdec.c 2023-10-02 20:17:27.000000000 +0800
623++++ nss-new/lib/util/derdec.c 2026-07-08 16:11:40.472218913 +0800
624+@@ -8,7 +8,7 @@
625+ static PRUint32
626+ der_indefinite_length(unsigned char *buf, unsigned char *end)
627+ {
628+- PRUint32 len, ret, dataLen;
629++ PRUint32 len, ret, dataLen, remaining;
630+ unsigned char tag, lenCode;
631+ int dataLenLen;
632+
633+@@ -20,6 +20,10 @@
634+
635+ tag = *buf++;
636+ lenCode = *buf++;
637++ if (len > UINT32_MAX - 2) {
638++ PORT_SetError(SEC_ERROR_BAD_DER);
639++ return 0;
640++ }
641+ len += 2;
642+
643+ if ((tag == 0) && (lenCode == 0)) {
644+@@ -30,12 +34,20 @@
645+ ret = der_indefinite_length(buf, end); /* recurse to find length */
646+ if (ret == 0)
647+ return 0;
648++ if (len > UINT32_MAX - ret) {
649++ PORT_SetError(SEC_ERROR_BAD_DER);
650++ return 0;
651++ }
652+ len += ret;
653+ buf += ret;
654+ } else { /* definite length */
655+ if (lenCode & 0x80) {
656+ /* Length of data is in multibyte format */
657+ dataLenLen = lenCode & 0x7f;
658++ if ((buf + dataLenLen) > end) {
659++ PORT_SetError(SEC_ERROR_BAD_DER);
660++ return 0;
661++ }
662+ switch (dataLenLen) {
663+ case 1:
664+ dataLen = buf[0];
665+@@ -52,7 +64,7 @@
666+ break;
667+ default:
668+ PORT_SetError(SEC_ERROR_BAD_DER);
669+- return SECFailure;
670++ return 0;
671+ }
672+ } else {
673+ /* Length of data is in single byte */
674+@@ -60,8 +72,20 @@
675+ dataLenLen = 0;
676+ }
677+
678++ remaining = (PRUint32)(end - buf);
679++ if (dataLen > remaining ||
680++ (PRUint32)dataLenLen > remaining - dataLen) {
681++ PORT_SetError(SEC_ERROR_BAD_DER);
682++ return 0;
683++ }
684++
685+ /* skip this item */
686+ buf = buf + dataLenLen + dataLen;
687++ if ((PRUint32)dataLenLen > UINT32_MAX - len ||
688++ dataLen > UINT32_MAX - len - (PRUint32)dataLenLen) {
689++ PORT_SetError(SEC_ERROR_BAD_DER);
690++ return 0;
691++ }
692+ len = len + dataLenLen + dataLen;
693+ }
694+ }
695+diff -uNr nss/lib/util/quickder.c nss-new/lib/util/quickder.c
696+--- nss/lib/util/quickder.c 2023-10-02 20:17:27.000000000 +0800
697++++ nss-new/lib/util/quickder.c 2026-07-08 16:11:40.472218913 +0800
698+@@ -485,6 +485,16 @@
699+ return rv;
700+ }
701+
702++/*
703++ * Check if multiplication of size by count would overflow a size_t.
704++ * Returns PR_TRUE on success, PR_FALSE if overflow would occur.
705++ */
706++static PRBool
707++MulSizeCheck(size_t size, size_t count)
708++{
709++ return (size == 0 || count <= SIZE_MAX / size);
710++}
711++
712+ static SECStatus
713+ DecodeGroup(void* dest,
714+ const SEC_ASN1Template* templateEntry,
715+@@ -525,17 +535,40 @@
716+ if (SECSuccess == rv) {
717+ /* allocate room for pointer array and entries */
718+ /* we want to allocate the array even if there is 0 entry */
719+- entries = (void**)PORT_ArenaZAlloc(arena, sizeof(void*) * (totalEntries + 1) + /* the extra one is for NULL termination */
720+- subTemplate->size * totalEntries);
721++ size_t allocationSize = 0;
722++ size_t arraySize = 0;
723++ size_t dataSize = 0;
724++ void* entriesData = NULL;
725++
726++ /* Check for potential integer overflow before allocating. */
727++ if (!MulSizeCheck(sizeof(void*), (size_t)totalEntries + 1) ||
728++ !MulSizeCheck(subTemplate->size, totalEntries)) {
729++ PORT_SetError(SEC_ERROR_BAD_DER);
730++ rv = SECFailure;
731++ }
732++
733++ if (SECSuccess == rv) {
734++ arraySize = sizeof(void*) * ((size_t)totalEntries + 1);
735++ dataSize = subTemplate->size * totalEntries;
736++ allocationSize = arraySize + dataSize;
737++ if (allocationSize < arraySize) {
738++ PORT_SetError(SEC_ERROR_BAD_DER);
739++ rv = SECFailure;
740++ }
741++ }
742++
743++ if (SECSuccess == rv) {
744++ entries = (void**)PORT_ArenaZAlloc(arena, allocationSize);
745++ }
746+
747+ if (entries) {
748+ entries[totalEntries] = NULL; /* terminate the array */
749+- } else {
750++ } else if (SECSuccess == rv) {
751+ PORT_SetError(SEC_ERROR_NO_MEMORY);
752+ rv = SECFailure;
753+ }
754+ if (SECSuccess == rv) {
755+- void* entriesData = (unsigned char*)entries + (unsigned long)(sizeof(void*) * (totalEntries + 1));
756++ entriesData = (unsigned char*)entries + arraySize;
757+ /* and fix the pointers in the array */
758+ PRUint32 entriesIndex = 0;
759+ for (entriesIndex = 0; entriesIndex < totalEntries; entriesIndex++) {
@@ -26,7 +26,7 @@
26Summary: Network Security Services26Summary: Network Security Services
27Name: nss27Name: nss
28Version: %{nss_version}28Version: %{nss_version}
29-Release: 929+Release: 10
30License: MPLv2.030License: MPLv2.0
31URL: http://www.mozilla.org/projects/security/pki/nss/31URL: http://www.mozilla.org/projects/security/pki/nss/
32Provides: nss-system-init32Provides: nss-system-init
@@ -60,6 +60,7 @@ Patch9003: Feature-nss-support-SM2-signature-algorithm.patch
60Patch9004: Feature-nss-fix-the-certificate-resolution-in-sm2.patch60Patch9004: Feature-nss-fix-the-certificate-resolution-in-sm2.patch
61Patch9005: Feature-fix-sm2-sm3-code-error.patch61Patch9005: Feature-fix-sm2-sm3-code-error.patch
62Patch9006: Feature-fix-sm3-code-error.patch62Patch9006: Feature-fix-sm3-code-error.patch
63+Patch9007: Fix-vulnerability-and-enhance-security.patch
63 64 
64%description65%description
65Network Security Services (NSS) is a set of libraries designed to66Network Security Services (NSS) is a set of libraries designed to
@@ -150,6 +151,7 @@ pushd nss
150%patch9004 -p1151%patch9004 -p1
151%patch9005 -p1152%patch9005 -p1
152%patch9006 -p1153%patch9006 -p1
154+%patch9007 -p1
153popd155popd
154 156 
155%build157%build
@@ -573,6 +575,9 @@ update-crypto-policies &>/dev/null||:
573%doc %{_mandir}/man*575%doc %{_mandir}/man*
574 576 
575%changelog577%changelog
578+* Fri Jul 10 2026 ganjianqing <ganjianqing@kylinos.cn> - 3.94.0-10
579+- fix vulnerability and enhance security
580+ 
576* Thu May 7 2026 yixiangzhike <yixiangzhike007@163.com> - 3.94.0-9581* Thu May 7 2026 yixiangzhike <yixiangzhike007@163.com> - 3.94.0-9
577- fix error order of HASH_AlgSM3 in SECRawHashObjects582- fix error order of HASH_AlgSM3 in SECRawHashObjects
578 583