Bug 1806394 r=nalexander

Differential Revision: https://phabricator.services.mozilla.com/D168294

@@ -56,35 +56,38 @@ int mar_read_entire_file(const char* filePath, uint32_t maxSize,
   return result;
 }

-int mar_extract_and_verify_signatures_fp(FILE* fp,
-                                         CryptoX_ProviderHandle provider,
-                                         CryptoX_PublicKey* keys,
-                                         uint32_t keyCount);
-int mar_verify_signatures_for_fp(FILE* fp, CryptoX_ProviderHandle provider,
-                                 CryptoX_PublicKey* keys,
-                                 const uint8_t* const* extractedSignatures,
-                                 uint32_t keyCount, uint32_t* numVerified);
+int mar_extract_and_verify_signatures(MarFile* mar,
+                                      CryptoX_ProviderHandle provider,
+                                      CryptoX_PublicKey* keys,
+                                      uint32_t keyCount);
+int mar_verify_extracted_signatures(MarFile* mar,
+                                    CryptoX_ProviderHandle provider,
+                                    CryptoX_PublicKey* keys,
+                                    const uint8_t* const* extractedSignatures,
+                                    uint32_t keyCount, uint32_t* numVerified);

 /**
- * Reads the specified number of bytes from the file pointer and
+ * Reads the specified number of bytes from the MAR buffer and
  * stores them in the passed buffer.
  *
- * @param  fp     The file pointer to read from.
+ * @param  mar    An opened MAR
+ * @param  mar_position
+ *                Our current position within the MAR file buffer.
  * @param  buffer The buffer to store the read results.
  * @param  size   The number of bytes to read, buffer must be
  *                at least of this size.
  * @param  ctxs   Pointer to the first element in an array of verify context.
  * @param  count  The number of elements in ctxs
  * @param  err    The name of what is being written to in case of error.
- * @return  0 on success
- *         -1 on read error
- *         -2 on verify update error
+ * @return  CryptoX_Success on success
+ *          CryptoX_Error   on error
  */
-int ReadAndUpdateVerifyContext(FILE* fp, void* buffer, uint32_t size,
-                               CryptoX_SignatureHandle* ctxs, uint32_t count,
-                               const char* err) {
+CryptoX_Result ReadAndUpdateVerifyContext(MarFile* mar, size_t* mar_position,
+                                          void* buffer, uint32_t size,
+                                          CryptoX_SignatureHandle* ctxs,
+                                          uint32_t count, const char* err) {
   uint32_t k;
-  if (!fp || !buffer || !ctxs || count == 0 || !err) {
+  if (!mar || !mar_position || !buffer || !ctxs || count == 0 || !err) {
     fprintf(stderr, "ERROR: Invalid parameter specified.\n");
     return CryptoX_Error;
   }
@@ -93,15 +96,15 @@ int ReadAndUpdateVerifyContext(FILE* fp, void* buffer, uint32_t size,
     return CryptoX_Success;
   }

-  if (fread(buffer, size, 1, fp) != 1) {
+  if (mar_read_buffer(mar, buffer, mar_position, size) != 0) {
     fprintf(stderr, "ERROR: Could not read %s\n", err);
     return CryptoX_Error;
   }

   for (k = 0; k < count; k++) {
     if (CryptoX_Failed(CryptoX_VerifyUpdate(&ctxs[k], buffer, size))) {
       fprintf(stderr, "ERROR: Could not update verify context for %s\n", err);
-      return -2;
+      return CryptoX_Error;
     }
   }
   return CryptoX_Success;
@@ -136,11 +139,6 @@ int mar_verify_signatures(MarFile* mar, const uint8_t* const* certData,
     goto failure;
   }

-  if (!mar->fp) {
-    fprintf(stderr, "ERROR: MAR file is not open.\n");
-    goto failure;
-  }
-
   if (CryptoX_Failed(CryptoX_InitCryptoProvider(&provider))) {
     fprintf(stderr, "ERROR: Could not init crytpo library.\n");
     goto failure;
@@ -154,7 +152,7 @@ int mar_verify_signatures(MarFile* mar, const uint8_t* const* certData,
     }
   }

-  rv = mar_extract_and_verify_signatures_fp(mar->fp, provider, keys, certCount);
+  rv = mar_extract_and_verify_signatures(mar, provider, keys, certCount);

 failure:

@@ -169,50 +167,41 @@ int mar_verify_signatures(MarFile* mar, const uint8_t* const* certData,

 /**
  * Extracts each signature from the specified MAR file,
- * then calls mar_verify_signatures_for_fp to verify each signature.
+ * then calls mar_verify_extracted_signatures to verify each signature.
  *
- * @param  fp       An opened MAR file handle
+ * @param  mar      An opened MAR
  * @param  provider A library provider
  * @param  keys     The public keys to use to verify the MAR
  * @param  keyCount The number of keys pointed to by keys
  * @return 0 on success
  */
-int mar_extract_and_verify_signatures_fp(FILE* fp,
-                                         CryptoX_ProviderHandle provider,
-                                         CryptoX_PublicKey* keys,
-                                         uint32_t keyCount) {
+int mar_extract_and_verify_signatures(MarFile* mar,
+                                      CryptoX_ProviderHandle provider,
+                                      CryptoX_PublicKey* keys,
+                                      uint32_t keyCount) {
   uint32_t signatureCount, signatureLen, numVerified = 0;
   uint32_t signatureAlgorithmIDs[MAX_SIGNATURES];
   uint8_t* extractedSignatures[MAX_SIGNATURES];
   uint32_t i;
+  size_t mar_position = 0;

   memset(signatureAlgorithmIDs, 0, sizeof(signatureAlgorithmIDs));
   memset(extractedSignatures, 0, sizeof(extractedSignatures));

-  if (!fp) {
+  if (!mar) {
     fprintf(stderr, "ERROR: Invalid file pointer passed.\n");
     return CryptoX_Error;
   }

-  /* To protect against invalid MAR files, we assumes that the MAR file
-     size is less than or equal to MAX_SIZE_OF_MAR_FILE. */
-  if (fseeko(fp, 0, SEEK_END)) {
-    fprintf(stderr, "ERROR: Could not seek to the end of the MAR file.\n");
-    return CryptoX_Error;
-  }
-  if (ftello(fp) > MAX_SIZE_OF_MAR_FILE) {
-    fprintf(stderr, "ERROR: MAR file is too large to be verified.\n");
-    return CryptoX_Error;
-  }
-
   /* Skip to the start of the signature block */
-  if (fseeko(fp, SIGNATURE_BLOCK_OFFSET, SEEK_SET)) {
+  if (mar_buffer_seek(mar, &mar_position, SIGNATURE_BLOCK_OFFSET) != 0) {
     fprintf(stderr, "ERROR: Could not seek to the signature block.\n");
     return CryptoX_Error;
   }

   /* Get the number of signatures */
-  if (fread(&signatureCount, sizeof(signatureCount), 1, fp) != 1) {
+  if (mar_read_buffer(mar, &signatureCount, &mar_position,
+                      sizeof(signatureCount)) != 0) {
     fprintf(stderr, "ERROR: Could not read number of signatures.\n");
     return CryptoX_Error;
   }
@@ -228,19 +217,21 @@ int mar_extract_and_verify_signatures_fp(FILE* fp,

   for (i = 0; i < signatureCount; i++) {
     /* Get the signature algorithm ID */
-    if (fread(&signatureAlgorithmIDs[i], sizeof(uint32_t), 1, fp) != 1) {
+    if (mar_read_buffer(mar, &signatureAlgorithmIDs[i], &mar_position,
+                        sizeof(uint32_t)) != 0) {
       fprintf(stderr, "ERROR: Could not read signatures algorithm ID.\n");
       return CryptoX_Error;
     }
     signatureAlgorithmIDs[i] = ntohl(signatureAlgorithmIDs[i]);

-    if (fread(&signatureLen, sizeof(uint32_t), 1, fp) != 1) {
+    if (mar_read_buffer(mar, &signatureLen, &mar_position, sizeof(uint32_t)) !=
+        0) {
       fprintf(stderr, "ERROR: Could not read signatures length.\n");
       return CryptoX_Error;
     }
     signatureLen = ntohl(signatureLen);

-    /* To protected against invalid input make sure the signature length
+    /* To protect against invalid input make sure the signature length
        isn't too big. */
     if (signatureLen > MAX_SIGNATURE_LENGTH) {
       fprintf(stderr, "ERROR: Signature length is too large to verify.\n");
@@ -249,10 +240,11 @@ int mar_extract_and_verify_signatures_fp(FILE* fp,

     extractedSignatures[i] = malloc(signatureLen);
     if (!extractedSignatures[i]) {
-      fprintf(stderr, "ERROR: Could allocate buffer for signature.\n");
+      fprintf(stderr, "ERROR: Could not allocate buffer for signature.\n");
       return CryptoX_Error;
     }
-    if (fread(extractedSignatures[i], signatureLen, 1, fp) != 1) {
+    if (mar_read_buffer(mar, extractedSignatures[i], &mar_position,
+                        signatureLen) != 0) {
       fprintf(stderr, "ERROR: Could not read extracted signature.\n");
       for (i = 0; i < signatureCount; ++i) {
         free(extractedSignatures[i]);
@@ -270,11 +262,8 @@ int mar_extract_and_verify_signatures_fp(FILE* fp,
     }
   }

-  if (ftello(fp) == -1) {
-    return CryptoX_Error;
-  }
-  if (mar_verify_signatures_for_fp(
-          fp, provider, keys, (const uint8_t* const*)extractedSignatures,
+  if (mar_verify_extracted_signatures(
+          mar, provider, keys, (const uint8_t* const*)extractedSignatures,
           signatureCount, &numVerified) == CryptoX_Error) {
     return CryptoX_Error;
   }
@@ -304,7 +293,7 @@ int mar_extract_and_verify_signatures_fp(FILE* fp,
  * certificate given, etc. The signature count must exactly match the number of
  * certificates given, and all signature verifications must succeed.
  *
- * @param  fp                   An opened MAR file handle
+ * @param  mar                  An opened MAR
  * @param  provider             A library provider
  * @param  keys                 A pointer to the first element in an
  *                              array of keys.
@@ -315,18 +304,18 @@ int mar_extract_and_verify_signatures_fp(FILE* fp,
  *                              the number of verified signatures.
  *                              This information can be useful for printing
  *                              error messages.
- * @return 0 on success, *numVerified == signatureCount.
+ * @return  CryptoX_Success on success, *numVerified == signatureCount.
  */
-int mar_verify_signatures_for_fp(FILE* fp, CryptoX_ProviderHandle provider,
-                                 CryptoX_PublicKey* keys,
-                                 const uint8_t* const* extractedSignatures,
-                                 uint32_t signatureCount,
-                                 uint32_t* numVerified) {
+CryptoX_Result mar_verify_extracted_signatures(
+    MarFile* mar, CryptoX_ProviderHandle provider, CryptoX_PublicKey* keys,
+    const uint8_t* const* extractedSignatures, uint32_t signatureCount,
+    uint32_t* numVerified) {
   CryptoX_SignatureHandle signatureHandles[MAX_SIGNATURES];
   char buf[BLOCKSIZE];
   uint32_t signatureLengths[MAX_SIGNATURES];
   uint32_t i;
   int rv = CryptoX_Error;
+  size_t mar_position = 0;

   memset(signatureHandles, 0, sizeof(signatureHandles));
   memset(signatureLengths, 0, sizeof(signatureLengths));
@@ -355,34 +344,28 @@ int mar_verify_signatures_for_fp(FILE* fp, CryptoX_ProviderHandle provider,
     }
   }

-  /* Skip to the start of the file */
-  if (fseeko(fp, 0, SEEK_SET)) {
-    fprintf(stderr, "ERROR: Could not seek to start of the file\n");
-    goto failure;
-  }
-
   /* Bytes 0-3: MAR1
      Bytes 4-7: index offset
      Bytes 8-15: size of entire MAR
    */
   if (CryptoX_Failed(ReadAndUpdateVerifyContext(
-          fp, buf, SIGNATURE_BLOCK_OFFSET + sizeof(uint32_t), signatureHandles,
-          signatureCount, "signature block"))) {
+          mar, &mar_position, buf, SIGNATURE_BLOCK_OFFSET + sizeof(uint32_t),
+          signatureHandles, signatureCount, "signature block"))) {
     goto failure;
   }

   /* Read the signature block */
   for (i = 0; i < signatureCount; i++) {
     /* Get the signature algorithm ID */
     if (CryptoX_Failed(ReadAndUpdateVerifyContext(
-            fp, &buf, sizeof(uint32_t), signatureHandles, signatureCount,
-            "signature algorithm ID"))) {
+            mar, &mar_position, &buf, sizeof(uint32_t), signatureHandles,
+            signatureCount, "signature algorithm ID"))) {
       goto failure;
     }

     if (CryptoX_Failed(ReadAndUpdateVerifyContext(
-            fp, &signatureLengths[i], sizeof(uint32_t), signatureHandles,
-            signatureCount, "signature length"))) {
+            mar, &mar_position, &signatureLengths[i], sizeof(uint32_t),
+            signatureHandles, signatureCount, "signature length"))) {
       goto failure;
     }
     signatureLengths[i] = ntohl(signatureLengths[i]);
@@ -392,20 +375,15 @@ int mar_verify_signatures_for_fp(FILE* fp, CryptoX_ProviderHandle provider,
     }

     /* Skip past the signature itself as those are not included */
-    if (fseeko(fp, signatureLengths[i], SEEK_CUR)) {
+    if (mar_buffer_seek(mar, &mar_position, signatureLengths[i]) != 0) {
       fprintf(stderr, "ERROR: Could not seek past signature.\n");
       goto failure;
     }
   }

   /* Read the rest of the file after the signature block */
-  while (!feof(fp)) {
-    int numRead = fread(buf, 1, BLOCKSIZE, fp);
-    if (ferror(fp)) {
-      fprintf(stderr, "ERROR: Error reading data block.\n");
-      goto failure;
-    }
-
+  while (mar_position < mar->data_len) {
+    int numRead = mar_read_buffer_max(mar, buf, &mar_position, BLOCKSIZE);
     for (i = 0; i < signatureCount; i++) {
       if (CryptoX_Failed(
               CryptoX_VerifyUpdate(&signatureHandles[i], buf, numRead))) {


More checks for correct header sizes

Reported-by: "P. Amsuo, Purdue University"

@@ -868,6 +868,9 @@ static inline void tcp_parse_option_mss(struct pico_socket_tcp *t, uint8_t len,
     if (tcpopt_len_check(idx, len, PICO_TCPOPTLEN_MSS) < 0)
         return;

+    if ((*idx + PICO_TCPOPTLEN_MSS) > len)
+        return;
+
     t->mss_ok = 1;
     mss = short_from(opt + *idx);
     *idx += (uint32_t)sizeof(uint16_t);
@@ -896,6 +899,10 @@ static int tcp_parse_options(struct pico_frame *f)
     uint8_t *opt = f->transport_hdr + PICO_SIZE_TCPHDR;
     uint32_t i = 0;
     f->timestamp = 0;
+
+    if (f->buffer + f->buffer_len > f->transport_hdr + f->transport_len)
+        return -1;
+
     while (i < (f->transport_len - PICO_SIZE_TCPHDR)) {
         uint8_t type =  opt[i++];
         uint8_t len;


Add missing pointer invalidation

ok tb
from jcs

This is errata/7.2/026_ssl.patch.sig

@@ -1,4 +1,4 @@
-/* $OpenBSD: s3_lib.c,v 1.238 2022/08/21 19:39:44 jsing Exp $ */
+/* $OpenBSD: s3_lib.c,v 1.238.2.1 2023/05/26 08:48:38 tb Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -1573,6 +1573,7 @@ ssl3_free(SSL *s)

 	sk_X509_NAME_pop_free(s->s3->hs.tls12.ca_names, X509_NAME_free);
 	sk_X509_pop_free(s->internal->verified_chain, X509_free);
+	s->internal->verified_chain = NULL;

 	tls1_transcript_free(s);
 	tls1_transcript_hash_free(s);


* FIX [transport] fix #1153 https://github.com/emqx/nanomq/issues/1153 for other transport

@@ -695,8 +695,15 @@ mqtts_tcptran_pipe_recv_cb(void *arg)
 				ack_cmd = CMD_PUBACK;
 			} else if (qos_pac == 2) {
 				ack_cmd = CMD_PUBREC;
+			} else {
+				log_warn("Wrong QoS level!");
+				rv = PROTOCOL_ERROR;
+				goto recv_error;
+			}
+			if ((packet_id = nni_msg_get_pub_pid(msg)) == 0) {
+				rv = PROTOCOL_ERROR;
+				goto recv_error;
 			}
-			packet_id = nni_msg_get_pub_pid(msg);
 			ack = true;
 		}
 		break;


Bug 1814597; r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D171401

@@ -1658,10 +1658,10 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,

   // Exit fullscreen if a website focuses another window
   if (StaticPrefs::full_screen_api_exit_on_windowRaise() &&
-      !isElementInActiveWindow && (aFlags & FLAG_RAISE) &&
-      (aFlags & FLAG_NONSYSTEMCALLER)) {
+      !isElementInActiveWindow && (aFlags & FLAG_RAISE)) {
     if (XRE_IsParentProcess()) {
       if (Document* doc = mActiveWindow ? mActiveWindow->GetDoc() : nullptr) {
+        Document::ClearPendingFullscreenRequests(doc);
         if (doc->GetFullscreenElement()) {
           LogWarningFullscreenWindowRaise(mFocusedElement);
           Document::AsyncExitFullscreen(doc);
@@ -1672,9 +1672,11 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
       if (activeBrowsingContext) {
         nsIDocShell* shell = activeBrowsingContext->GetDocShell();
         if (shell) {
-          Document* doc = shell->GetDocument();
-          if (doc && doc->GetFullscreenElement()) {
-            Document::AsyncExitFullscreen(doc);
+          if (Document* doc = shell->GetDocument()) {
+            Document::ClearPendingFullscreenRequests(doc);
+            if (doc->GetFullscreenElement()) {
+              Document::AsyncExitFullscreen(doc);
+            }
           }
         } else {
           mozilla::dom::ContentChild* contentChild =


net: nfc: Fix use-after-free caused by nfc_llcp_find_local

This commit fixes several use-after-free that caused by function
nfc_llcp_find_local(). For example, one UAF can happen when below buggy
time window occurs.

// nfc_genl_llc_get_params   | // nfc_unregister_device
                             |
dev = nfc_get_device(idx);   | device_lock(...)
if (!dev)                    | dev->shutting_down = true;
    return -ENODEV;          | device_unlock(...);
                             |
device_lock(...);            |   // nfc_llcp_unregister_device
                             |   nfc_llcp_find_local()
nfc_llcp_find_local(...);    |
                             |   local_cleanup()
if (!local) {                |
    rc = -ENODEV;            |     // nfc_llcp_local_put
    goto exit;               |     kref_put(.., local_release)
}                            |
                             |       // local_release
                             |       list_del(&local->list)
  // nfc_genl_send_params    |       kfree()
  local->dev->idx !!!UAF!!!  |
                             |

and the crash trace for the one of the discussed UAF like:

BUG: KASAN: slab-use-after-free in nfc_genl_llc_get_params+0x72f/0x780  net/nfc/netlink.c:1045
Read of size 8 at addr ffff888105b0e410 by task 20114

Call Trace:
 <TASK>
 __dump_stack  lib/dump_stack.c:88 [inline]
 dump_stack_lvl+0x72/0xa0  lib/dump_stack.c:106
 print_address_description  mm/kasan/report.c:319 [inline]
 print_report+0xcc/0x620  mm/kasan/report.c:430
 kasan_report+0xb2/0xe0  mm/kasan/report.c:536
 nfc_genl_send_params  net/nfc/netlink.c:999 [inline]
 nfc_genl_llc_get_params+0x72f/0x780  net/nfc/netlink.c:1045
 genl_family_rcv_msg_doit.isra.0+0x1ee/0x2e0  net/netlink/genetlink.c:968
 genl_family_rcv_msg  net/netlink/genetlink.c:1048 [inline]
 genl_rcv_msg+0x503/0x7d0  net/netlink/genetlink.c:1065
 netlink_rcv_skb+0x161/0x430  net/netlink/af_netlink.c:2548
 genl_rcv+0x28/0x40  net/netlink/genetlink.c:1076
 netlink_unicast_kernel  net/netlink/af_netlink.c:1339 [inline]
 netlink_unicast+0x644/0x900  net/netlink/af_netlink.c:1365
 netlink_sendmsg+0x934/0xe70  net/netlink/af_netlink.c:1913
 sock_sendmsg_nosec  net/socket.c:724 [inline]
 sock_sendmsg+0x1b6/0x200  net/socket.c:747
 ____sys_sendmsg+0x6e9/0x890  net/socket.c:2501
 ___sys_sendmsg+0x110/0x1b0  net/socket.c:2555
 __sys_sendmsg+0xf7/0x1d0  net/socket.c:2584
 do_syscall_x64  arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x3f/0x90  arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x72/0xdc
RIP: 0033:0x7f34640a2389
RSP: 002b:00007f3463415168 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 00007f34641c1f80 RCX: 00007f34640a2389
RDX: 0000000000000000 RSI: 0000000020000240 RDI: 0000000000000006
RBP: 00007f34640ed493 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007ffe38449ecf R14: 00007f3463415300 R15: 0000000000022000
 </TASK>

Allocated by task 20116:
 kasan_save_stack+0x22/0x50  mm/kasan/common.c:45
 kasan_set_track+0x25/0x30  mm/kasan/common.c:52
 ____kasan_kmalloc  mm/kasan/common.c:374 [inline]
 __kasan_kmalloc+0x7f/0x90  mm/kasan/common.c:383
 kmalloc  include/linux/slab.h:580 [inline]
 kzalloc  include/linux/slab.h:720 [inline]
 nfc_llcp_register_device+0x49/0xa40  net/nfc/llcp_core.c:1567
 nfc_register_device+0x61/0x260  net/nfc/core.c:1124
 nci_register_device+0x776/0xb20  net/nfc/nci/core.c:1257
 virtual_ncidev_open+0x147/0x230  drivers/nfc/virtual_ncidev.c:148
 misc_open+0x379/0x4a0  drivers/char/misc.c:165
 chrdev_open+0x26c/0x780  fs/char_dev.c:414
 do_dentry_open+0x6c4/0x12a0  fs/open.c:920
 do_open  fs/namei.c:3560 [inline]
 path_openat+0x24fe/0x37e0  fs/namei.c:3715
 do_filp_open+0x1ba/0x410  fs/namei.c:3742
 do_sys_openat2+0x171/0x4c0  fs/open.c:1356
 do_sys_open  fs/open.c:1372 [inline]
 __do_sys_openat  fs/open.c:1388 [inline]
 __se_sys_openat  fs/open.c:1383 [inline]
 __x64_sys_openat+0x143/0x200  fs/open.c:1383
 do_syscall_x64  arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x3f/0x90  arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x72/0xdc

Freed by task 20115:
 kasan_save_stack+0x22/0x50  mm/kasan/common.c:45
 kasan_set_track+0x25/0x30  mm/kasan/common.c:52
 kasan_save_free_info+0x2e/0x50  mm/kasan/generic.c:521
 ____kasan_slab_free  mm/kasan/common.c:236 [inline]
 ____kasan_slab_free  mm/kasan/common.c:200 [inline]
 __kasan_slab_free+0x10a/0x190  mm/kasan/common.c:244
 kasan_slab_free  include/linux/kasan.h:162 [inline]
 slab_free_hook  mm/slub.c:1781 [inline]
 slab_free_freelist_hook  mm/slub.c:1807 [inline]
 slab_free  mm/slub.c:3787 [inline]
 __kmem_cache_free+0x7a/0x190  mm/slub.c:3800
 local_release  net/nfc/llcp_core.c:174 [inline]
 kref_put  include/linux/kref.h:65 [inline]
 nfc_llcp_local_put  net/nfc/llcp_core.c:182 [inline]
 nfc_llcp_local_put  net/nfc/llcp_core.c:177 [inline]
 nfc_llcp_unregister_device+0x206/0x290  net/nfc/llcp_core.c:1620
 nfc_unregister_device+0x160/0x1d0  net/nfc/core.c:1179
 virtual_ncidev_close+0x52/0xa0  drivers/nfc/virtual_ncidev.c:163
 __fput+0x252/0xa20  fs/file_table.c:321
 task_work_run+0x174/0x270  kernel/task_work.c:179
 resume_user_mode_work  include/linux/resume_user_mode.h:49 [inline]
 exit_to_user_mode_loop  kernel/entry/common.c:171 [inline]
 exit_to_user_mode_prepare+0x108/0x110  kernel/entry/common.c:204
 __syscall_exit_to_user_mode_work  kernel/entry/common.c:286 [inline]
 syscall_exit_to_user_mode+0x21/0x50  kernel/entry/common.c:297
 do_syscall_64+0x4c/0x90  arch/x86/entry/common.c:86
 entry_SYSCALL_64_after_hwframe+0x72/0xdc

Last potentially related work creation:
 kasan_save_stack+0x22/0x50  mm/kasan/common.c:45
 __kasan_record_aux_stack+0x95/0xb0  mm/kasan/generic.c:491
 kvfree_call_rcu+0x29/0xa80  kernel/rcu/tree.c:3328
 drop_sysctl_table+0x3be/0x4e0  fs/proc/proc_sysctl.c:1735
 unregister_sysctl_table.part.0+0x9c/0x190  fs/proc/proc_sysctl.c:1773
 unregister_sysctl_table+0x24/0x30  fs/proc/proc_sysctl.c:1753
 neigh_sysctl_unregister+0x5f/0x80  net/core/neighbour.c:3895
 addrconf_notify+0x140/0x17b0  net/ipv6/addrconf.c:3684
 notifier_call_chain+0xbe/0x210  kernel/notifier.c:87
 call_netdevice_notifiers_info+0xb5/0x150  net/core/dev.c:1937
 call_netdevice_notifiers_extack  net/core/dev.c:1975 [inline]
 call_netdevice_notifiers  net/core/dev.c:1989 [inline]
 dev_change_name+0x3c3/0x870  net/core/dev.c:1211
 dev_ifsioc+0x800/0xf70  net/core/dev_ioctl.c:376
 dev_ioctl+0x3d9/0xf80  net/core/dev_ioctl.c:542
 sock_do_ioctl+0x160/0x260  net/socket.c:1213
 sock_ioctl+0x3f9/0x670  net/socket.c:1316
 vfs_ioctl  fs/ioctl.c:51 [inline]
 __do_sys_ioctl  fs/ioctl.c:870 [inline]
 __se_sys_ioctl  fs/ioctl.c:856 [inline]
 __x64_sys_ioctl+0x19e/0x210  fs/ioctl.c:856
 do_syscall_x64  arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x3f/0x90  arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x72/0xdc

The buggy address belongs to the object at ffff888105b0e400
 which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 16 bytes inside of
 freed 1024-byte region [ffff888105b0e400, ffff888105b0e800)

The buggy address belongs to the physical page:
head:ffffea000416c200 order:3 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x200000000010200(slab|head|node=0|zone=2)
raw: 0200000000010200 ffff8881000430c0 ffffea00044c7010 ffffea0004510e10
raw: 0000000000000000 00000000000a000a 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff888105b0e300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff888105b0e380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff888105b0e400: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                         ^
 ffff888105b0e480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff888105b0e500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb

In summary, this patch solves those use-after-free by

1. Re-implement the nfc_llcp_find_local(). The current version does not
grab the reference when getting the local from the linked list.  For
example, the llcp_sock_bind() gets the reference like below:

// llcp_sock_bind()

    local = nfc_llcp_find_local(dev); // A
    ..... \
           | raceable
    ..... /
    llcp_sock->local = nfc_llcp_local_get(local); // B

There is an apparent race window that one can  drop the reference
and free the local object fetched in (A) before (B) gets the reference.

2. Some callers of the nfc_llcp_find_local() do not grab the reference
at all. For example, the nfc_genl_llc_{{get/set}_params/sdreq} functions.
We add the nfc_llcp_local_put() for them. Moreover, we add the necessary
error handling function to put the reference.

3. Add the nfc_llcp_remove_local() helper. The local object is removed
from the linked list in local_release() when all reference is gone. This
patch removes it when nfc_llcp_unregister_device() is called.

Therefore, every caller of nfc_llcp_find_local() will get a reference
even when the nfc_llcp_unregister_device() is called. This promises no
use-after-free for the local object is ever possible.

Fixes: 52feb444a903 ("NFC: Extend netlink interface for LTO, RW, and MIUX parameters support")
Fixes: c7aa12252f51 ("NFC: Take a reference on the LLCP local pointer when creating a socket")
Signed-off-by: Lin Ma <linma@zju.edu.cn>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

@@ -1039,11 +1039,14 @@ static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info)
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 	if (!msg) {
 		rc = -ENOMEM;
-		goto exit;
+		goto put_local;
 	}

 	rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq);

+put_local:
+	nfc_llcp_local_put(local);
+
 exit:
 	device_unlock(&dev->dev);

@@ -1105,7 +1108,7 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
 	if (info->attrs[NFC_ATTR_LLC_PARAM_LTO]) {
 		if (dev->dep_link_up) {
 			rc = -EINPROGRESS;
-			goto exit;
+			goto put_local;
 		}

 		local->lto = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_LTO]);
@@ -1117,6 +1120,9 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
 	if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX])
 		local->miux = cpu_to_be16(miux);

+put_local:
+	nfc_llcp_local_put(local);
+
 exit:
 	device_unlock(&dev->dev);

@@ -1172,7 +1178,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)

 		if (rc != 0) {
 			rc = -EINVAL;
-			goto exit;
+			goto put_local;
 		}

 		if (!sdp_attrs[NFC_SDP_ATTR_URI])
@@ -1191,7 +1197,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
 		sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len);
 		if (sdreq == NULL) {
 			rc = -ENOMEM;
-			goto exit;
+			goto put_local;
 		}

 		tlvs_len += sdreq->tlv_len;
@@ -1201,10 +1207,14 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)

 	if (hlist_empty(&sdreq_list)) {
 		rc = -EINVAL;
-		goto exit;
+		goto put_local;
 	}

 	rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len);
+
+put_local:
+	nfc_llcp_local_put(local);
+
 exit:
 	device_unlock(&dev->dev);


Security fix for AC flag poisoning and MCDT

This PR does the following
- Ensuring the AC flag along with other system/control flags are always cleared upon enclave enter
- Update the inital MXCSR value to 0x1FBF and put lfence after MXCSR load (via LDMXCSR, XRSTOR, or FXRSTOR)
  for the MCDT mitigation

Signed-off-by: Ming-Wei Shih <mishih@microsoft.com>

@@ -641,15 +641,17 @@ OE_INLINE void _handle_oret(
     td->oret_arg = arg;

     /* Restore the FXSTATE and flags */
-    asm volatile("pushq %[rflags] \n\t" // Restore flags.
-                 "popfq \n\t"
-                 "fldcw %[fcw] \n\t"     // Restore x87 control word
-                 "ldmxcsr %[mxcsr] \n\t" // Restore MXCSR
-                 : [mxcsr] "=m"(callsite->mxcsr),
-                   [fcw] "=m"(callsite->fcw),
-                   [rflags] "=m"(callsite->rflags)
-                 :
-                 : "cc");
+    asm volatile(
+        "pushq %[rflags] \n\t" // Restore flags.
+        "popfq \n\t"
+        "fldcw %[fcw] \n\t"     // Restore x87 control word
+        "ldmxcsr %[mxcsr] \n\t" // Restore MXCSR
+        "lfence \n\t" // MXCSR Configuration Dependent Timing (MCDT) mitigation
+        : [mxcsr] "=m"(callsite->mxcsr),
+          [fcw] "=m"(callsite->fcw),
+          [rflags] "=m"(callsite->rflags)
+        :
+        : "cc");

     oe_longjmp(&callsite->jmpbuf, 1);
 }


xfrm: fix crash in XFRM_MSG_GETSA netlink handler

If we hit any of the error conditions inside xfrm_dump_sa(), then
xfrm_state_walk_init() never gets called. However, we still call
xfrm_state_walk_done() from xfrm_dump_sa_done(), which will crash
because the state walk was never initialized properly.

We can fix this by setting cb->args[0] only after we've processed the
first element and checking this before calling xfrm_state_walk_done().

Fixes: d3623099d3 ("ipsec: add support of limited SA dump")
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>

@@ -896,7 +896,8 @@ static int xfrm_dump_sa_done(struct netlink_callback *cb)
 	struct sock *sk = cb->skb->sk;
 	struct net *net = sock_net(sk);

-	xfrm_state_walk_done(walk, net);
+	if (cb->args[0])
+		xfrm_state_walk_done(walk, net);
 	return 0;
 }

@@ -921,8 +922,6 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
 		u8 proto = 0;
 		int err;

-		cb->args[0] = 1;
-
 		err = nlmsg_parse(cb->nlh, 0, attrs, XFRMA_MAX,
 				  xfrma_policy);
 		if (err < 0)
@@ -939,6 +938,7 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
 			proto = nla_get_u8(attrs[XFRMA_PROTO]);

 		xfrm_state_walk_init(walk, proto, filter);
+		cb->args[0] = 1;
 	}

 	(void) xfrm_state_walk(net, walk, dump_one_state, &info);


Use isolated uninstaller temp directory

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7388 212acab6-be3b-0410-9dea-997c60f758d6

@@ -348,60 +348,69 @@ EXTERN_C void NSISWinMainNOCRT()
     }
     else
     {
-      int x, admin = UserIsAdminGrpMember();
-
-      mystrcat(state_temp_dir,_T("~nsu"));
-      if (admin) mystrcat(state_temp_dir,_T("A")); // Don't lock down the directory used by non-admins
-      mystrcat(state_temp_dir,_T(".tmp"));
-
-      // check if already running from uninstaller temp dir
-      // this prevents recursive uninstaller calls
-      if (!lstrcmpi(state_temp_dir,state_exe_directory))
-        goto end;
-
-      admin ? CreateRestrictedDirectory(state_temp_dir) : CreateNormalDirectory(state_temp_dir);
-      SetCurrentDirectory(state_temp_dir);
-
-      if (!(*state_install_directory))
-        mystrcpy(state_install_directory,state_exe_directory);
+      int admin = UserIsAdminGrpMember();
+      WORD tries; // 0xfffe attempts or bust
+      size_t cchtmpslash = mystrlen(state_temp_dir);
+      LPTSTR unexe = g_usrvars[5], unexecmd = g_usrvars[6];

       mystrcpy(g_usrvars[0], realcmds);
-      SET2CHAR(g_usrvars[1], _T("A\0"));
-
-      for (x = 0; x < 26; x ++)
+      if (!(*state_install_directory))
       {
-        static TCHAR buf2[NSIS_MAX_STRLEN];
-
-        GetNSISString(buf2,g_header->str_uninstchild); // $TEMP\Un_$1.exe
+        mystrcpy(state_install_directory, state_exe_directory);
+      }

-        DeleteFile(buf2); // clean up after all the other ones if they are there
+      for (tries = 0; ++tries != 0;)
+      {
+        DWORD retry = 0, ec;
+retry_un_dir:
+        wsprintf(state_temp_dir + cchtmpslash, _T("~nsu%X.tmp"), tries);
+        GetNSISString(unexe, g_header->str_uninstchild); // '$TEMP\Un.exe'
+        if (admin)
+        {
+          ec = CreateRestrictedDirectory(state_temp_dir);
+        }
+        else
+        {
+          ec = CreateNormalDirectory(state_temp_dir);
+        }

-        if (m_Err) // not done yet
+        if (ec)
         {
-          // copy file
-          if (CopyFile(state_exe_path,buf2,TRUE))
+          // Delete previous uninstaller
+          if (DeleteFile(unexe))
+          {
+            myDelete(state_temp_dir, DEL_DIR|DEL_RECURSE);
+            if (!retry++) goto retry_un_dir;
+          }
+        }
+        else
+        {
+          HANDLE hProc;
+          SetCurrentDirectory(state_temp_dir);
+#ifdef NSIS_SUPPORT_MOVEONREBOOT
+          MoveFileOnReboot(state_temp_dir, NULL);
+#endif
+          if (CopyFile(state_exe_path, unexe, TRUE))
           {
-            HANDLE hProc;
 #ifdef NSIS_SUPPORT_MOVEONREBOOT
-            MoveFileOnReboot(buf2,NULL);
+            MoveFileOnReboot(unexe, NULL);
 #endif
-            GetNSISString(buf2,g_header->str_uninstcmd); // '"$TEMP\Un_$1.exe" $0 _?=$INSTDIR\'
-            hProc=myCreateProcess(buf2);
+            GetNSISString(unexecmd, g_header->str_uninstcmd); // '"$TEMP\Un.exe" $0 _?=$INSTDIR\'
+            hProc = myCreateProcess(unexecmd);
             if (hProc)
             {
               CloseHandle(hProc);
-              // success
-              m_Err = 0;
+              m_Err = 0; // Success
+            }
+            else if (!retry++ && !file_exists(unexe))
+            {
+              // Another instance deleted us between CopyFile and CreateProcess
+              goto retry_un_dir;
             }
           }
+          break; // We called CreateProcess; success or failure, we are done.
         }
-        (*(((NSIS_STRING *)g_usrvars)[1]))++;
       }
-
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
-      MoveFileOnReboot(state_temp_dir,NULL);
-#endif
-
       goto end;
     }
   }


@@ -81,6 +81,7 @@ static void avidmx_setup(GF_Filter *filter, GF_AVIDmxCtx *ctx)
 	if (ctx->use_file_fps) {
 		Double fps = AVI_frame_rate(ctx->avi);
 		gf_media_get_video_timing(fps, &ctx->fps.num, &ctx->fps.den);
+		if (!ctx->fps.num) ctx->fps.num = ctx->fps.den = 1000;
 	}

 	dur.den = ctx->fps.num;


ikev1: merge accept_self_delete() into accept_delete()

If accept_delete() determins that the current ISAKMP SA was deleted
return immediately (do not process notifies or other delete messages)

@@ -1794,7 +1794,6 @@ void process_packet_tail(struct msg_digest *md)
 	const struct state_v1_microcode *smc = md->smc;
 	enum state_kind from_state = smc->state;
 	bool new_iv_set = md->new_iv_set;
-	bool self_delete = false;

 	if (md->hdr.isa_flags & ISAKMP_FLAGS_v1_ENCRYPTION) {

@@ -2269,38 +2268,40 @@ void process_packet_tail(struct msg_digest *md)
 		}
 	}

+	pexpect(st == md->v1_st); /* could be NULL */
+
 	for (struct payload_digest *p = md->chain[ISAKMP_NEXT_D];
 	     p != NULL; p = p->next) {
-		self_delete |= accept_delete(md, p);
-		if (DBGP(DBG_BASE)) {
-			DBG_dump("del:", p->pbs.cur,
-				 pbs_left(&p->pbs));
+		if (!accept_delete(&st, md, p)) {
+			ldbg(md->md_logger, "bailing with bad delete message");
+			return;
 		}
-		if (md->v1_st != st) {
-			pexpect(md->v1_st == NULL);
-			dbg("zapping ST as accept_delete() zapped MD.ST");
-			st = md->v1_st;
+		if (st == NULL) {
+			ldbg(md->md_logger, "bailing due to self-inflicted delete");
+			return;
 		}
 	}

+	pexpect(st == md->v1_st); /* could be NULL */
+
 	for (struct payload_digest *p = md->chain[ISAKMP_NEXT_VID];
 	     p != NULL; p = p->next) {
 		handle_v1_vendorid(md, pbs_in_left_as_shunk(&p->pbs),
 				   (st != NULL ? st->st_logger : md->md_logger));
 	}

-	if (self_delete) {
-		accept_self_delete(md);
-		st = md->v1_st;
-		/* note: st ought to be NULL from here on */
-	}
+	pexpect(st == md->v1_st); /* could be NULL */

-	pexpect(st == md->v1_st);
-	statetime_t start = statetime_start(md->v1_st);
 	/*
-	 * XXX: danger - the .informational() processor deletes ST;
-	 * and then tunnels this loss through MD.ST.
+	 * XXX: Danger.
+	 *
+	 * ++ the .informational() processor deletes ST; and then
+	 * tries to tunnel this loss back through MD.ST.
+	 *
+	 * ++ the .aggressive() processor replaces .V1_ST with the IKE
+	 * SA?
 	 */
+	statetime_t start = statetime_start(st);
 	stf_status e = smc->processor(st, md);
 	complete_v1_state_transition(md->v1_st, md, e);
 	statetime_stop(&start, "%s()", __func__);


udp: crash fix when receiving multi-packet uploads

multi-packet sets aren't supported in UDP. It was trying to write an
error message in response, but no mc_resp object was initialized at the
time, leading to a null reference crash.

Instead drop the packet quietly since that's a pretty fatal bug anyway
and keeps the parser simplified.

For credits see accompanying release notes.

@@ -1183,9 +1183,9 @@ bool resp_has_stack(conn *c) {

 void out_string(conn *c, const char *str) {
     size_t len;
+    assert(c != NULL);
     mc_resp *resp = c->resp;

-    assert(c != NULL);
     // if response was original filled with something, but we're now writing
     // out an error or similar, have to reset the object first.
     // TODO: since this is often redundant with allocation, how many callers
@@ -2604,7 +2604,6 @@ static enum try_read_result try_read_udp(conn *c) {

         /* If this is a multi-packet request, drop it. */
         if (buf[4] != 0 || buf[5] != 1) {
-            out_string(c, "SERVER_ERROR multi-packet request not supported");
             return READ_NO_DATA_RECEIVED;
         }


Fix oobread crash in DWARF parser (tests_64924) ##crash

Reported by giantbranch of NSFOCUS TIANJI Lab

@@ -383,21 +383,18 @@ static inline ut64 dwarf_read_offset(bool is_64bit, const ut8 **buf, const ut8 *
 	if (is_64bit) {
 		result = READ64 (*buf);
 	} else {
-		result = READ32 (*buf);
+		result = (ut64)READ32 (*buf);
 	}
 	return result;
 }

 static inline ut64 dwarf_read_address(size_t size, const ut8 **buf, const ut8 *buf_end) {
 	ut64 result;
 	switch (size) {
-		case 2:
-		result = READ16 (*buf); break;
-		case 4:
-		result = READ32 (*buf); break;
-		case 8:
-		result = READ64 (*buf); break;
-		default:
+	case 2: result = READ16 (*buf); break;
+	case 4: result = READ32 (*buf); break;
+	case 8: result = READ64 (*buf); break;
+	default:
 		result = 0;
 		*buf += size;
 		eprintf ("Weird dwarf address size: %zu.", size);
@@ -1857,8 +1854,7 @@ static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
  * @param sdb
  * @return const ut8* Updated buffer
  */
-static const ut8 *parse_die(const ut8 *buf, const ut8 *buf_end, RBinDwarfAbbrevDecl *abbrev,
-		RBinDwarfCompUnitHdr *hdr, RBinDwarfDie *die, const ut8 *debug_str, size_t debug_str_len, Sdb *sdb) {
+static const ut8 *parse_die(const ut8 *buf, const ut8 *buf_end, RBinDwarfAbbrevDecl *abbrev, RBinDwarfCompUnitHdr *hdr, RBinDwarfDie *die, const ut8 *debug_str, size_t debug_str_len, Sdb *sdb) {
 	size_t i;
 	for (i = 0; i < abbrev->count - 1; i++) {
 		memset (&die->attr_values[i], 0, sizeof (die->attr_values[i]));
@@ -1868,9 +1864,8 @@ static const ut8 *parse_die(const ut8 *buf, const ut8 *buf_end, RBinDwarfAbbrevD

 		RBinDwarfAttrValue *attribute = &die->attr_values[i];

-		bool is_valid_string_form = (attribute->attr_form == DW_FORM_strp ||
-			attribute->attr_form == DW_FORM_string) &&
-			attribute->string.content;
+		bool is_string = (attribute->attr_form == DW_FORM_strp || attribute->attr_form == DW_FORM_string);
+		bool is_valid_string_form = is_string && attribute->string.content;
 		// TODO  does this have a purpose anymore?
 		// Or atleast it needs to rework becase there will be
 		// more comp units -> more comp dirs and only the last one will be kept
@@ -1880,7 +1875,6 @@ static const ut8 *parse_die(const ut8 *buf, const ut8 *buf_end, RBinDwarfAbbrevD
 		}
 		die->count++;
 	}
-
 	return buf;
 }


Sanitize libxml2 globals before parsing

Fixes GHSA-3qrf-m4j2-pcrr.

To parse a document with libxml2, you first need to create a parsing context.
The parsing context contains parsing options (e.g. XML_NOENT to substitute
entities) that the application (in this case PHP) can set.
Unfortunately, libxml2 also supports providing default set options.
For example, if you call xmlSubstituteEntitiesDefault(1) then the XML_NOENT
option will be added to the parsing options every time you create a parsing
context **even if the application never requested XML_NOENT**.

Third party extensions can override these globals, in particular the
substitute entity global. This causes entity substitution to be
unexpectedly active.

Fix it by setting the parsing options to a sane known value.
For API calls that depend on global state we introduce
PHP_LIBXML_SANITIZE_GLOBALS() and PHP_LIBXML_RESTORE_GLOBALS().
For other APIs that work directly with a context we introduce
php_libxml_sanitize_parse_ctxt_options().

@@ -114,7 +114,9 @@ PHP_METHOD(DOMDocumentFragment, appendXML) {
 	}

 	if (data) {
+		PHP_LIBXML_SANITIZE_GLOBALS(parse);
 		err = xmlParseBalancedChunkMemory(nodep->doc, NULL, NULL, 0, (xmlChar *) data, &lst);
+		PHP_LIBXML_RESTORE_GLOBALS(parse);
 		if (err != 0) {
 			RETURN_FALSE;
 		}


BUG/MAJOR: http: reject any empty content-length header value

The content-length header parser has its dedicated function, in order
to take extreme care about invalid, unparsable, or conflicting values.
But there's a corner case in it, by which it stops comparing values
when reaching the end of the header. This has for a side effect that
an empty value or a value that ends with a comma does not deserve
further analysis, and it acts as if the header was absent.

While this is not necessarily a problem for the value ending with a
comma as it will be cause a header folding and will disappear, it is a
problem for the first isolated empty header because this one will not
be recontructed when next ones are seen, and will be passed as-is to the
backend server. A vulnerable HTTP/1 server hosted behind haproxy that
would just use this first value as "0" and ignore the valid one would
then not be protected by haproxy and could be attacked this way, taking
the payload for an extra request.

In field the risk depends on the server. Most commonly used servers
already have safe content-length parsers, but users relying on haproxy
to protect a known-vulnerable server might be at risk (and the risk of
a bug even in a reputable server should never be dismissed).

A configuration-based work-around consists in adding the following rule
in the frontend, to explicitly reject requests featuring an empty
content-length header that would have not be folded into an existing
one:

    http-request deny if { hdr_len(content-length) 0 }

The real fix consists in adjusting the parser so that it always expects a
value at the beginning of the header or after a comma. It will now reject
requests and responses having empty values anywhere in the C-L header.

This needs to be backported to all supported versions. Note that the
modification was made to functions h1_parse_cont_len_header() and
http_parse_cont_len_header(). Prior to 2.8 the latter was in
h2_parse_cont_len_header(). One day the two should be refused but the
former is also used by Lua.

The HTTP messaging reg-tests were completed to test these cases.

Thanks to Ben Kallus of Dartmouth College and Narf Industries for
reporting this! (this is in GH #2237).

@@ -707,13 +707,20 @@ int http_parse_cont_len_header(struct ist *value, unsigned long long *body_len,
 	struct ist word;
 	int check_prev = not_first;

-	word.ptr = value->ptr - 1; // -1 for next loop's pre-increment
+	word.ptr = value->ptr;
 	e = value->ptr + value->len;

-	while (++word.ptr < e) {
+	while (1) {
+		if (word.ptr >= e) {
+			/* empty header or empty value */
+			goto fail;
+		}
+
 		/* skip leading delimiter and blanks */
-		if (unlikely(HTTP_IS_LWS(*word.ptr)))
+		if (unlikely(HTTP_IS_LWS(*word.ptr))) {
+			word.ptr++;
 			continue;
+		}

 		/* digits only now */
 		for (cl = 0, n = word.ptr; n < e; n++) {
@@ -751,6 +758,13 @@ int http_parse_cont_len_header(struct ist *value, unsigned long long *body_len,
 		/* OK, store this result as the one to be indexed */
 		*body_len = cl;
 		*value = word;
+
+		/* Now either n==e and we're done, or n points to the comma,
+		 * and we skip it and continue.
+		 */
+		if (n++ == e)
+			break;
+
 		word.ptr = n;
 		check_prev = 1;
 	}


Add nts_cookie_not_server

See #794, but that bug was accidentally fixed
by bd596fa36738fab8de3e38a29ed0f218b7dda28d
when I updated the cookie_decode counters.

@@ -103,10 +103,11 @@ AES_SIV_CTX* cookie_ctx;

 /* Statistics for ntpq */
 uint64_t nts_cookie_make = 0;
+uint64_t nts_cookie_not_server = 0;
 uint64_t nts_cookie_decode_total = 0;
-uint64_t nts_cookie_decode_current = 0;
-uint64_t nts_cookie_decode_old = 0;	/* one day old */
-uint64_t nts_cookie_decode_old2 = 0;	/* two days old */
+uint64_t nts_cookie_decode_current = 0; /* less than one day old, current key*/
+uint64_t nts_cookie_decode_old = 0;	/* zero to one day old */
+uint64_t nts_cookie_decode_old2 = 0;	/* one to two days old */
 uint64_t nts_cookie_decode_older = 0;	/* more than 2 days old */
 uint64_t nts_cookie_decode_too_old = 0;
 uint64_t nts_cookie_decode_error = 0;
@@ -383,6 +384,11 @@ bool nts_unpack_cookie(uint8_t *cookie, int cookielen,
 	if (NULL == cookie_ctx)
 		return false;	/* We aren't initialized yet. */

+	if (0 == nts_nKeys) {
+		nts_cookie_not_server++;
+		return false;  /* We are not a NTS enabled server. */
+	}
+
 	/* We may get garbage from the net */
 	if (cookielen > NTS_MAX_COOKIELEN)
 		return false;


Merge pull request from GHSA-2hjx-rm4f-r9hw

CVE-2023-42822

@@ -454,7 +454,7 @@ xrdp_painter_text_width(struct xrdp_painter *self, const char *text)

     for (index = 0; index < len; index++)
     {
-        font_item = self->font->font_items + wstr[index];
+        font_item = XRDP_FONT_GET_CHAR(self->font, wstr[index]);
         rv = rv + font_item->incby;
     }

@@ -837,7 +837,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
             total_height = 0;
             for (index = 0; index < len; index++)
             {
-                font_item = font->font_items + wstr[index];
+                font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
                 k = font_item->incby;
                 total_width += k;
                 /* Use the nominal height of the font to work out the
@@ -875,7 +875,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
                                      draw_rect.bottom - draw_rect.top);
                     for (index = 0; index < len; index++)
                     {
-                        font_item = font->font_items + wstr[index];
+                        font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
                         g_memset(&pat, 0, sizeof(pat));
                         pat.format = PT_FORMAT_c1;
                         pat.width = font_item->width;
@@ -917,7 +917,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,

     for (index = 0; index < len; index++)
     {
-        font_item = font->font_items + wstr[index];
+        font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
         i = xrdp_cache_add_char(self->wm->cache, font_item);
         f = HIWORD(i);
         c = LOWORD(i);


core: crypto_bignum_free(): add indirection and set pointer to NULL

To prevent human mistake, crypto_bignum_free() sets the location of the
bignum pointer to NULL after freeing it.

Signed-off-by: Jihwan Park <jihwp@amazon.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Joakim Bech <joakim.bech@linaro.org>
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>

@@ -743,9 +743,9 @@ static TEE_Result do_alloc_keypair(struct ecc_keypair *s, uint32_t type,
 		goto err;
 	return TEE_SUCCESS;
 err:
-	crypto_bignum_free(s->d);
-	crypto_bignum_free(s->x);
-	crypto_bignum_free(s->y);
+	crypto_bignum_free(&s->d);
+	crypto_bignum_free(&s->x);
+	crypto_bignum_free(&s->y);
 	return TEE_ERROR_OUT_OF_MEMORY;
 }

@@ -764,8 +764,8 @@ static TEE_Result do_alloc_publickey(struct ecc_public_key *s, uint32_t type,
 		goto err;
 	return TEE_SUCCESS;
 err:
-	crypto_bignum_free(s->x);
-	crypto_bignum_free(s->y);
+	crypto_bignum_free(&s->x);
+	crypto_bignum_free(&s->y);
 	return TEE_ERROR_OUT_OF_MEMORY;
 }

@@ -774,8 +774,8 @@ static void do_free_publickey(struct ecc_public_key *s)
 	if (!s)
 		return;

-	crypto_bignum_free(s->x);
-	crypto_bignum_free(s->y);
+	crypto_bignum_free(&s->x);
+	crypto_bignum_free(&s->y);
 }

 static struct drvcrypt_ecc driver_ecc = {


@@ -87,10 +87,13 @@ struct bignum *crypto_bignum_allocate(size_t size_bits)
 	return (struct bignum *)bn;
 }

-void crypto_bignum_free(struct bignum *s)
+void crypto_bignum_free(struct bignum **s)
 {
-	mbedtls_mpi_free((mbedtls_mpi *)s);
-	free(s);
+	assert(s);
+
+	mbedtls_mpi_free((mbedtls_mpi *)*s);
+	free(*s);
+	*s = NULL;
 }

 void crypto_bignum_clear(struct bignum *s)


PR29677, Field `the_bfd` of `asymbol` is uninitialised

Besides not initialising the_bfd of synthetic symbols, counting
symbols when sizing didn't match symbols created if there were any
dynsyms named "".  We don't want synthetic symbols without names
anyway, so get rid of them.  Also, simplify and correct sanity checks.

	PR 29677
	* mach-o.c (bfd_mach_o_get_synthetic_symtab): Rewrite.

@@ -938,11 +938,9 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd,
   bfd_mach_o_symtab_command *symtab = mdata->symtab;
   asymbol *s;
   char * s_start;
-  char * s_end;
   unsigned long count, i, j, n;
   size_t size;
   char *names;
-  char *nul_name;
   const char stub [] = "$stub";

   *ret = NULL;
@@ -955,27 +953,27 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd,
   /* We need to allocate a bfd symbol for every indirect symbol and to
      allocate the memory for its name.  */
   count = dysymtab->nindirectsyms;
-  size = count * sizeof (asymbol) + 1;
-
+  size = 0;
   for (j = 0; j < count; j++)
     {
-      const char * strng;
       unsigned int isym = dysymtab->indirect_syms[j];
+      const char *str;

       /* Some indirect symbols are anonymous.  */
-      if (isym < symtab->nsyms && (strng = symtab->symbols[isym].symbol.name))
-	/* PR 17512: file: f5b8eeba.  */
-	size += strnlen (strng, symtab->strsize - (strng - symtab->strtab)) + sizeof (stub);
+      if (isym < symtab->nsyms
+	  && (str = symtab->symbols[isym].symbol.name) != NULL)
+	{
+	  /* PR 17512: file: f5b8eeba.  */
+	  size += strnlen (str, symtab->strsize - (str - symtab->strtab));
+	  size += sizeof (stub);
+	}
     }

-  s_start = bfd_malloc (size);
+  s_start = bfd_malloc (size + count * sizeof (asymbol));
   s = *ret = (asymbol *) s_start;
   if (s == NULL)
     return -1;
   names = (char *) (s + count);
-  nul_name = names;
-  *names++ = 0;
-  s_end = s_start + size;

   n = 0;
   for (i = 0; i < mdata->nsects; i++)
@@ -997,47 +995,39 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd,
 	  entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);

 	  /* PR 17512: file: 08e15eec.  */
-	  if (first >= count || last >= count || first > last)
+	  if (first >= count || last > count || first > last)
 	    goto fail;

 	  for (j = first; j < last; j++)
 	    {
 	      unsigned int isym = dysymtab->indirect_syms[j];
-
-	      /* PR 17512: file: 04d64d9b.  */
-	      if (((char *) s) + sizeof (* s) > s_end)
-		goto fail;
-
-	      s->flags = BSF_GLOBAL | BSF_SYNTHETIC;
-	      s->section = sec->bfdsection;
-	      s->value = addr - sec->addr;
-	      s->udata.p = NULL;
+	      const char *str;
+	      size_t len;

 	      if (isym < symtab->nsyms
-		  && symtab->symbols[isym].symbol.name)
+		  && (str = symtab->symbols[isym].symbol.name) != NULL)
 		{
-		  const char *sym = symtab->symbols[isym].symbol.name;
-		  size_t len;
-
-		  s->name = names;
-		  len = strlen (sym);
-		  /* PR 17512: file: 47dfd4d2.  */
-		  if (names + len >= s_end)
+		  /* PR 17512: file: 04d64d9b.  */
+		  if (n >= count)
 		    goto fail;
-		  memcpy (names, sym, len);
-		  names += len;
-		  /* PR 17512: file: 18f340a4.  */
-		  if (names + sizeof (stub) >= s_end)
+		  len = strnlen (str, symtab->strsize - (str - symtab->strtab));
+		  /* PR 17512: file: 47dfd4d2, 18f340a4.  */
+		  if (size < len + sizeof (stub))
 		    goto fail;
-		  memcpy (names, stub, sizeof (stub));
-		  names += sizeof (stub);
+		  memcpy (names, str, len);
+		  memcpy (names + len, stub, sizeof (stub));
+		  s->name = names;
+		  names += len + sizeof (stub);
+		  size -= len + sizeof (stub);
+		  s->the_bfd = symtab->symbols[isym].symbol.the_bfd;
+		  s->flags = BSF_GLOBAL | BSF_SYNTHETIC;
+		  s->section = sec->bfdsection;
+		  s->value = addr - sec->addr;
+		  s->udata.p = NULL;
+		  s++;
+		  n++;
 		}
-	      else
-		s->name = nul_name;
-
 	      addr += entry_size;
-	      s++;
-	      n++;
 	    }
 	  break;
 	default:


@@ -447,12 +447,12 @@ char *gf_bt_get_next(GF_BTParser *parser, Bool point_break)
 	i=0;
 	has_quote = 0;
 	while (go) {
+		if (parser->line_pos+i>=parser->line_size) break;
+
 		if (parser->line_buffer[parser->line_pos + i] == '\"') {
 			if (!has_quote) has_quote = 1;
 			else has_quote = 0;
 			parser->line_pos += 1;
-
-			if (parser->line_pos+i==parser->line_size) break;
 			continue;
 		}
 		if (!has_quote) {


patch 9.0.1840: [security] use-after-free in do_ecmd

Problem:  use-after-free in do_ecmd
Solution: Verify oldwin pointer after reset_VIsual()

Signed-off-by: Christian Brabandt <cb@256bit.org>

@@ -699,6 +699,8 @@ static char *(features[]) =

 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1840,
 /**/
     1839,
 /**/


Remove dangerous API for returning small primes from an internal table.

@@ -170,13 +170,6 @@ static void bn_exp(bn_t c, const bn_t a, const bn_t b, const bn_t m) {
 /* Public definitions                                                         */
 /*============================================================================*/

-dig_t bn_get_prime(int pos) {
-	if (pos >= BASIC_TESTS) {
-		return 0;
-	}
-	return primes[pos];
-}
-
 int bn_is_prime(const bn_t a) {
 	int result;


Huge commit improving the API to use size_t instead of int.

@@ -745,7 +745,7 @@ int ep2_size_bin(const ep2_t a, int pack);
  * @throw ERR_NO_VALID		- if the encoded point is invalid.
  * @throw ERR_NO_BUFFER		- if the buffer capacity is invalid.
  */
-void ep2_read_bin(ep2_t a, const uint8_t *bin, int len);
+void ep2_read_bin(ep2_t a, const uint8_t *bin, size_t len);

 /**
  * Writes a prime elliptic curve pointer over a quadratic extension to a byte
@@ -757,7 +757,7 @@ void ep2_read_bin(ep2_t a, const uint8_t *bin, int len);
  * @param[in] pack			- the flag to indicate point compression.
  * @throw ERR_NO_BUFFER		- if the buffer capacity is invalid.
  */
-void ep2_write_bin(uint8_t *bin, int len, const ep2_t a, int pack);
+void ep2_write_bin(uint8_t *bin, size_t len, const ep2_t a, int pack);

 /**
  * Negates a point represented in affine coordinates in an elliptic curve over
@@ -1060,7 +1060,8 @@ void ep2_mul_sim_trick(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q, cons
  * @param[in] q				- the second point to multiply.
  * @param[in] m				- the second integer,
  */
-void ep2_mul_sim_inter(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q, const bn_t m);
+void ep2_mul_sim_inter(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q,
+			const bn_t m);

 /**
  * Multiplies and adds two prime elliptic curve points simultaneously using
@@ -1072,7 +1073,8 @@ void ep2_mul_sim_inter(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q, cons
  * @param[in] q				- the second point to multiply.
  * @param[in] m				- the second integer,
  */
-void ep2_mul_sim_joint(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q, const bn_t m);
+void ep2_mul_sim_joint(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q,
+			const bn_t m);

 /**
  * Multiplies simultaneously elements from a prime elliptic curve.
@@ -1083,7 +1085,7 @@ void ep2_mul_sim_joint(ep2_t r, const ep2_t p, const bn_t k, const ep2_t q, cons
  * @param[out] k			- the integer scalars.
  * @param[out] n			- the number of elements to multiply.
  */
-void ep2_mul_sim_lot(ep2_t r, const ep2_t p[], const bn_t k[], int n);
+void ep2_mul_sim_lot(ep2_t r, const ep2_t p[], const bn_t k[], size_t n);

 /**
  * Multiplies and adds the generator and a prime elliptic curve point
@@ -1105,7 +1107,7 @@ void ep2_mul_sim_gen(ep2_t r, const bn_t k, const ep2_t q, const bn_t m);
  * @param[in] k				- the small scalars.
  * @param[in] len			- the number of points to multiply.
  */
-void ep2_mul_sim_dig(ep2_t r, const ep2_t p[], const dig_t k[], int len);
+void ep2_mul_sim_dig(ep2_t r, const ep2_t p[], const dig_t k[], size_t len);

 /**
  * Converts a point to affine coordinates.
@@ -1134,7 +1136,7 @@ void ep2_norm_sim(ep2_t *r, const ep2_t *t, int n);
  * @param[in] uniform_bytes		- the array of uniform bytes to map.
  * @param[in] len			- the array length in bytes.
  */
-void ep2_map_from_field(ep2_t p, const uint8_t *uniform_bytes, int len);
+void ep2_map_from_field(ep2_t p, const uint8_t *uniform_bytes, size_t len);

 /**
  * Maps a byte array to a point in an elliptic curve over a quadratic extension.
@@ -1143,7 +1145,7 @@ void ep2_map_from_field(ep2_t p, const uint8_t *uniform_bytes, int len);
  * @param[in] msg			- the byte array to map.
  * @param[in] len			- the array length in bytes.
  */
-void ep2_map(ep2_t p, const uint8_t *msg, int len);
+void ep2_map(ep2_t p, const uint8_t *msg, size_t len);

 /**
  * Maps a byte array to a point in an elliptic curve over a quadratic extension
@@ -1155,7 +1157,8 @@ void ep2_map(ep2_t p, const uint8_t *msg, int len);
  * @param[in] dst			- the domain separatoin tag.
  * @param[in] dst_len		- the domain separation tag length in bytes.
  */
-void ep2_map_dst(ep2_t p, const uint8_t *msg, int len, const uint8_t *dst, int dst_len);
+void ep2_map_dst(ep2_t p, const uint8_t *msg, size_t len, const uint8_t *dst,
+		size_t dst_len);

 /**
  * Computes a power of the Gailbraith-Lin-Scott homomorphism of a point
@@ -1385,7 +1388,7 @@ int ep4_size_bin(const ep4_t a, int pack);
  * @throw ERR_NO_VALID		- if the encoded point is invalid.
  * @throw ERR_NO_BUFFER		- if the buffer capacity is invalid.
  */
-void ep4_read_bin(ep4_t a, const uint8_t *bin, int len);
+void ep4_read_bin(ep4_t a, const uint8_t *bin, size_t len);

 /**
  * Writes a prime elliptic curve pointer over a quartic extension to a byte
@@ -1397,7 +1400,7 @@ void ep4_read_bin(ep4_t a, const uint8_t *bin, int len);
  * @param[in] pack			- the flag to indicate compression.
  * @throw ERR_NO_BUFFER		- if the buffer capacity is invalid.
  */
-void ep4_write_bin(uint8_t *bin, int len, const ep4_t a, int pack);
+void ep4_write_bin(uint8_t *bin, size_t len, const ep4_t a, int pack);

 /**
  * Negates a point represented in affine coordinates in an elliptic curve over
@@ -1723,7 +1726,7 @@ void ep4_mul_sim_joint(ep4_t r, const ep4_t p, const bn_t k, const ep4_t q, cons
  * @param[in] k			- the integer scalars.
  * @param[in] n			- the number of elements to multiply.
  */
-void ep4_mul_sim_lot(ep4_t r, const ep4_t p[], const bn_t k[], int n);
+void ep4_mul_sim_lot(ep4_t r, const ep4_t p[], const bn_t k[], size_t n);

 /**
  * Multiplies and adds the generator and a prime elliptic curve point
@@ -1745,7 +1748,7 @@ void ep4_mul_sim_gen(ep4_t r, const bn_t k, const ep4_t q, const bn_t m);
  * @param[in] k				- the small scalars.
  * @param[in] len			- the number of points to multiply.
  */
-void ep4_mul_sim_dig(ep4_t r, const ep4_t p[], const dig_t k[], int len);
+void ep4_mul_sim_dig(ep4_t r, const ep4_t p[], const dig_t k[], size_t len);

 /**
  * Converts a point to affine coordinates.
@@ -1771,7 +1774,7 @@ void ep4_norm_sim(ep4_t *r, const ep4_t *t, int n);
  * @param[in] msg			- the byte array to map.
  * @param[in] len			- the array length in bytes.
  */
-void ep4_map(ep4_t p, const uint8_t *msg, int len);
+void ep4_map(ep4_t p, const uint8_t *msg, size_t len);

 /**
  * Maps a byte array to a point in an elliptic curve over a quartic extension
@@ -1783,7 +1786,8 @@ void ep4_map(ep4_t p, const uint8_t *msg, int len);
  * @param[in] dst			- the domain separatoin tag.
  * @param[in] dst_len		- the domain separation tag length in bytes.
  */
-void ep4_map_dst(ep4_t p, const uint8_t *msg, int len, const uint8_t *dst, int dst_len);
+void ep4_map_dst(ep4_t p, const uint8_t *msg, size_t len, const uint8_t *dst,
+		size_t dst_len);

 /**
  * Computes a power of the Gailbraith-Lin-Scott homomorphism of a point


@@ -276,7 +276,7 @@ int bn_is_prime_rabin(const bn_t a) {
 		bn_sub_dig(n1, a, 1);
 		bn_copy(r, n1);
 		s = 0;
-		while (bn_is_even(r)) {
+		while (!bn_is_zero(r) && bn_is_even(r)) {
 			s++;
 			bn_rsh(r, r, 1);
 		}
@@ -401,7 +401,7 @@ int bn_is_prime_solov(const bn_t a) {

 #if BN_GEN == BASIC || !defined(STRIP)

-void bn_gen_prime_basic(bn_t a, int bits) {
+void bn_gen_prime_basic(bn_t a, size_t bits) {
 	while (1) {
 		do {
 			bn_rand(a, RLC_POS, bits);
@@ -416,7 +416,7 @@ void bn_gen_prime_basic(bn_t a, int bits) {

 #if BN_GEN == SAFEP || !defined(STRIP)

-void bn_gen_prime_safep(bn_t a, int bits) {
+void bn_gen_prime_safep(bn_t a, size_t bits) {
 	while (1) {
 		do {
 			bn_rand(a, RLC_POS, bits);
@@ -440,7 +440,7 @@ void bn_gen_prime_safep(bn_t a, int bits) {

 #if BN_GEN == STRON || !defined(STRIP)

-void bn_gen_prime_stron(bn_t a, int bits) {
+void bn_gen_prime_stron(bn_t a, size_t bits) {
 	dig_t i, j;
 	int found, k;
 	bn_t r, s, t;
@@ -519,7 +519,7 @@ void bn_gen_prime_stron(bn_t a, int bits) {

 #endif

-int bn_gen_prime_factor(bn_t a, bn_t b, int abits, int bbits) {
+int bn_gen_prime_factor(bn_t a, bn_t b, size_t abits, size_t bbits) {
 	bn_t t;
 	int result = RLC_OK;


@@ -72,8 +72,8 @@ int cp_sokaka_gen_prv(sokaka_t k, const char *id, bn_t master) {

 int cp_sokaka_key(uint8_t *key, size_t key_len, const char *id1,
 		const sokaka_t k, const char *id2) {
-	int len1 = strlen(id1), len2 = strlen(id2);
-	int size, first = 0, result = RLC_OK;
+	size_t size, len1 = strlen(id1), len2 = strlen(id2);
+	int first = 0, result = RLC_OK;
 	uint8_t *buf;
 	g1_t p;
 	g2_t q;


@@ -242,7 +242,7 @@ int ed_size_bin(const ed_t a, int pack) {
 	return size;
 }

-void ed_read_bin(ed_t a, const uint8_t *bin, int len) {
+void ed_read_bin(ed_t a, const uint8_t *bin, size_t len) {
 	if (len == 1) {
 		if (bin[0] == 0) {
 			ed_set_infty(a);
@@ -297,7 +297,7 @@ void ed_read_bin(ed_t a, const uint8_t *bin, int len) {
 	}
 }

-void ed_write_bin(uint8_t *bin, int len, const ed_t a, int pack) {
+void ed_write_bin(uint8_t *bin, size_t len, const ed_t a, int pack) {
 	ed_t t;

 	ed_null(t);


@@ -243,7 +243,7 @@ int ep2_size_bin(const ep2_t a, int pack) {
 	return size;
 }

-void ep2_read_bin(ep2_t a, const uint8_t *bin, int len) {
+void ep2_read_bin(ep2_t a, const uint8_t *bin, size_t len) {
 	if (len == 1) {
 		if (bin[0] == 0) {
 			ep2_set_infty(a);
@@ -293,7 +293,7 @@ void ep2_read_bin(ep2_t a, const uint8_t *bin, int len) {
 	}
 }

-void ep2_write_bin(uint8_t *bin, int len, const ep2_t a, int pack) {
+void ep2_write_bin(uint8_t *bin, size_t len, const ep2_t a, int pack) {
 	ep2_t t;

 	ep2_null(t);


@@ -62,15 +62,15 @@ int fp_is_even(const fp_t a) {
 	return 0;
 }

-int fp_get_bit(const fp_t a, int bit) {
+int fp_get_bit(const fp_t a, size_t bit) {
 	int d;

 	RLC_RIP(bit, d, bit);

 	return (a[d] >> bit) & 1;
 }

-void fp_set_bit(fp_t a, int bit, int value) {
+void fp_set_bit(fp_t a, size_t bit, int value) {
 	int d;
 	dig_t mask;

@@ -85,7 +85,7 @@ void fp_set_bit(fp_t a, int bit, int value) {
 	}
 }

-int fp_bits(const fp_t a) {
+size_t fp_bits(const fp_t a) {
 	int i = RLC_FP_DIGS - 1;

 	while (i >= 0 && a[i] == 0) {
@@ -157,9 +157,9 @@ void fp_print(const fp_t a) {
 	}
 }

-int fp_size_str(const fp_t a, int radix) {
+size_t fp_size_str(const fp_t a, unsigned int radix) {
 	bn_t t;
-	int digits = 0;
+	size_t digits = 0;

 	bn_null(t);

@@ -179,7 +179,7 @@ int fp_size_str(const fp_t a, int radix) {
 	return digits;
 }

-void fp_read_str(fp_t a, const char *str, int len, int radix) {
+void fp_read_str(fp_t a, const char *str, size_t len, unsigned int radix) {
 	bn_t t;

 	bn_null(t);
@@ -208,7 +208,7 @@ void fp_read_str(fp_t a, const char *str, int len, int radix) {
 	}
 }

-void fp_write_str(char *str, int len, const fp_t a, int radix) {
+void fp_write_str(char *str, size_t len, const fp_t a, unsigned int radix) {
 	bn_t t;

 	bn_null(t);
@@ -227,7 +227,7 @@ void fp_write_str(char *str, int len, const fp_t a, int radix) {
 	}
 }

-void fp_read_bin(fp_t a, const uint8_t *bin, int len) {
+void fp_read_bin(fp_t a, const uint8_t *bin, size_t len) {
 	bn_t t;

 	bn_null(t);
@@ -253,7 +253,7 @@ void fp_read_bin(fp_t a, const uint8_t *bin, int len) {
 				} else {
 					fp_prime_conv(a, t);
 				}
-			}
+			}
 		}
 	}
 	RLC_CATCH_ANY {
@@ -264,7 +264,7 @@ void fp_read_bin(fp_t a, const uint8_t *bin, int len) {
 	}
 }

-void fp_write_bin(uint8_t *bin, int len, const fp_t a) {
+void fp_write_bin(uint8_t *bin, size_t len, const fp_t a) {
 	bn_t t;

 	bn_null(t);


@@ -40,7 +40,7 @@

 #if MD_MAP == SH384 || !defined(STRIP)

-void md_map_sh384(uint8_t *hash, const uint8_t *msg, int len) {
+void md_map_sh384(uint8_t *hash, const uint8_t *msg, size_t len) {
 	SHA384Context ctx;

 	if (SHA384Reset(&ctx) != shaSuccess) {


@@ -234,7 +234,7 @@ static int util(void) {
 		} TEST_END;

 		TEST_CASE("reading and writing a positive number are consistent") {
-			int len = RLC_CEIL(RLC_BN_BITS, 8);
+			size_t len = RLC_CEIL(RLC_BN_BITS, 8);
 			bn_rand(a, RLC_POS, RLC_BN_BITS);
 			for (int j = 2; j <= 64; j++) {
 				bits = bn_size_str(a, j);
@@ -262,7 +262,7 @@ static int util(void) {
 		TEST_END;

 		TEST_CASE("reading and writing a negative number are consistent") {
-			int len = RLC_CEIL(RLC_BN_BITS, 8);
+			size_t len = RLC_CEIL(RLC_BN_BITS, 8);
 			bn_rand(a, RLC_NEG, RLC_BN_BITS);
 			for (int j = 2; j <= 64; j++) {
 				bits = bn_size_str(a, j);
@@ -1139,8 +1139,9 @@ static int exponentiation(void) {
 }

 static int square_root(void) {
-	int bits, code = RLC_ERR;
+	size_t bits;
 	bn_t a, b, c;
+	int code = RLC_ERR;

 	bn_null(a);
 	bn_null(b);
@@ -1938,9 +1939,10 @@ static int factor(void) {
 static int recoding(void) {
 	int code = RLC_ERR;
 	bn_t a, b, c, v1[3], v2[3];
-	int w, k, l;
+	int w, k;
 	uint8_t d[RLC_BN_BITS + 1];
 	int8_t e[2 * (RLC_BN_BITS + 1)];
+	size_t l;

 	bn_null(a);
 	bn_null(b);


@@ -42,6 +42,7 @@ int handle__publish(struct mosquitto *context)
 	uint8_t header = context->in_packet.command;
 	int res = 0;
 	struct mosquitto_msg_store *msg, *stored = NULL;
+	struct mosquitto_client_msg *cmsg_stored = NULL;
 	size_t len;
 	uint16_t slen;
 	char *topic_mount;
@@ -287,24 +288,24 @@ int handle__publish(struct mosquitto *context)
 	}

 	if(msg->qos > 0){
-		db__message_store_find(context, msg->source_mid, &stored);
+		db__message_store_find(context, msg->source_mid, &cmsg_stored);
 	}

-	if(stored && msg->source_mid != 0 &&
-			(stored->qos != msg->qos
-			 || stored->payloadlen != msg->payloadlen
-			 || strcmp(stored->topic, msg->topic)
-			 || memcmp(stored->payload, msg->payload, msg->payloadlen) )){
+	if(cmsg_stored && cmsg_stored->store && msg->source_mid != 0 &&
+			(cmsg_stored->store->qos != msg->qos
+			 || cmsg_stored->store->payloadlen != msg->payloadlen
+			 || strcmp(cmsg_stored->store->topic, msg->topic)
+			 || memcmp(cmsg_stored->store->payload, msg->payload, msg->payloadlen) )){

 		log__printf(NULL, MOSQ_LOG_WARNING, "Reused message ID %u from %s detected. Clearing from storage.", msg->source_mid, context->id);
 		db__message_remove_incoming(context, msg->source_mid);
-		stored = NULL;
+		cmsg_stored = NULL;
 	}

-	if(!stored){
+	if(!cmsg_stored){
 		if(msg->qos == 0
 				|| db__ready_for_flight(context, mosq_md_in, msg->qos)
-				|| db__ready_for_queue(context, msg->qos, &context->msgs_in)){
+				){

 			dup = 0;
 			rc = db__message_store(context, msg, message_expiry_interval, 0, mosq_mo_client);
@@ -316,10 +317,13 @@ int handle__publish(struct mosquitto *context)
 		}
 		stored = msg;
 		msg = NULL;
+		dup = 0;
 	}else{
 		db__msg_store_free(msg);
 		msg = NULL;
-		dup = 1;
+		stored = cmsg_stored->store;
+		cmsg_stored->dup++;
+		dup = cmsg_stored->dup;
 	}

 	switch(stored->qos){
@@ -345,11 +349,17 @@ int handle__publish(struct mosquitto *context)
 			}else{
 				res = 0;
 			}
+
 			/* db__message_insert() returns 2 to indicate dropped message
 			 * due to queue. This isn't an error so don't disconnect them. */
 			/* FIXME - this is no longer necessary due to failing early above */
 			if(!res){
-				if(send__pubrec(context, stored->source_mid, 0, NULL)) rc = 1;
+				if(dup == 0 || dup == 1){
+					rc2 = send__pubrec(context, stored->source_mid, 0, NULL);
+					if(rc2) rc = rc2;
+				}else{
+					return MOSQ_ERR_PROTOCOL;
+				}
 			}else if(res == 1){
 				rc = 1;
 			}
@@ -374,6 +384,9 @@ int handle__publish(struct mosquitto *context)
 		}
 		db__msg_store_free(msg);
 	}
+	if(context->out_packet_count >= db.config->max_queued_messages){
+		rc = MQTT_RC_QUOTA_EXCEEDED;
+	}
 	return rc;
 }


exfat2img: fix out-of-bounds write in read_file_dentry_set

if SecondaryCount is greater than (2 + the max number
of File Name entries), writing to memory outside
the node->name could happen.

Reported-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>

@@ -319,7 +319,7 @@ static int read_file_dentry_set(struct exfat_de_iter *iter,
 	if (!node)
 		return -ENOMEM;

-	for (i = 2; i <= file_de->file_num_ext; i++) {
+	for (i = 2; i <= MIN(file_de->file_num_ext, 1 + MAX_NAME_DENTRIES); i++) {
 		ret = exfat_de_iter_get(iter, i, &dentry);
 		if (ret || dentry->type != EXFAT_NAME)
 			break;


Merge of 1912385 from trunk:

  *) mod_http2: fixed a bug in handling of stream timeouts.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1912991 13f79535-47bb-0310-9956-ffa450edef68

@@ -1264,6 +1264,14 @@ int h2_stream_is_ready(h2_stream *stream)
     return 0;
 }

+int h2_stream_wants_send_data(h2_stream *stream)
+{
+    H2_STRM_ASSERT_MAGIC(stream, H2_STRM_MAGIC_OK);
+    return h2_stream_is_ready(stream) &&
+           ((stream->out_buffer && !APR_BRIGADE_EMPTY(stream->out_buffer)) ||
+            (stream->output && !h2_beam_empty(stream->output)));
+}
+
 int h2_stream_is_at(const h2_stream *stream, h2_stream_state_t state)
 {
     H2_STRM_ASSERT_MAGIC(stream, H2_STRM_MAGIC_OK);


backport of https://github.com/apache/httpd/pull/364

Merge 1907696,1907697 from trunk:

  *) mod_http2: new directive 'H2MaxDataFrameLen n' to limit the maximum
     amount of response body bytes put into a single HTTP/2 DATA frame.
     Setting this to 0 places no limit (but the max size allowed by the
     protocol is observed).
     The module, by default, tries to use the maximum size possible, which is
     somewhat around 16KB. This sets the maximum. When less response data is
     available, smaller frames will be sent.

Merge r1909769 from trunk (plus sync mod_http2.xml)

  *) mod_http2: v2.0.15 with the following fixes and improvements
     - New directive 'H2EarlyHint name value' to add headers to a response,
       picked up already when a "103 Early Hints" response is sent. 'name' and
       'value' must comply to the HTTP field restrictions.
       This directive can be repeated several times and header fields of the
       same names add. Sending a 'Link' header with 'preload' relation will
       also cause a HTTP/2 PUSH if enabled and supported by the client.
     - Fixed an issue where requests were not logged and accounted in a timely
       fashion when the connection returns to "keepalive" handling, e.g. when
       the request served was the last outstanding one.
       This led to late appearance in access logs with wrong duration times
       reported.
     - Accurately report the bytes sent for a request in the '%O' Log format.
       This addresses #203, a long outstanding issue where mod_h2 has reported
       numbers over-eagerly from internal buffering and not what has actually
       been placed on the connection.
       The numbers are now the same with and without H2CopyFiles enabled.

Merge r1910157 from trunk

 * mod_proxy_http2: fixed using the wrong "bucket_alloc" from the backend
   connection when sending data on the frontend one. This caused crashes
   or infinite loops in rare situations.
 * mod_proxy_http2: fixed a bug in retry/response handling that could lead
   to wrong status codes or HTTP messages send at the end of response bodies
   exceeding the announced content-length.
 * mod_proxy_http2: fix retry handling to not leak temporary errors.
   On detecting that that an existing connection was shutdown by the other
   side, a 503 response leaked even though the request was retried on a
   fresh connection.
 * mod_http2: fixed a bug that did cleanup of consumed and pending buckets in
   the wrong order when a bucket_beam was destroyed.

Merge of 1910331,1910386,1910441 from trunk

  *) mod_http2: fixed a bug in flushing pending data on an already closed
     connection that could lead to a busy loop, preventing the HTTP/2 session
     to close down successfully. Fixed PR 66624.
     Fixed a bug that could lead to a crash in main connection
     output handling. This occured only when the last request on a HTTP/2
     connection had been processed and the session decided to shut down.
     This could lead to an attempt to send a final GOAWAY while the previous
     write was still in progress. See PR 66646.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1910699 13f79535-47bb-0310-9956-ffa450edef68

@@ -61,6 +61,7 @@ struct h2_conn_ctx_t {
     int has_final_response;          /* final HTTP response passed on out */
     apr_status_t last_err;           /* APR_SUCCES or last error encountered in filters */

+    apr_off_t bytes_sent;            /* c2: bytes acutaly sent via c1 */
     /* atomic */ apr_uint32_t started; /* c2: processing was started */
     apr_time_t started_at;           /* c2: when processing started */
     /* atomic */ apr_uint32_t done;  /* c2: processing has finished */


@@ -63,7 +63,22 @@ typedef struct h2_stream_monitor {
                                              trigger a state change */
 } h2_stream_monitor;

+#ifdef AP_DEBUG
+#define H2_STRM_MAGIC_OK     0x5354524d
+#define H2_STRM_MAGIC_SDEL   0x5344454c
+#define H2_STRM_MAGIC_PDEL   0x5044454c
+
+#define H2_STRM_ASSIGN_MAGIC(s,m)  ((s)->magic = m)
+#define H2_STRM_ASSERT_MAGIC(s,m)  ap_assert((s)->magic == m)
+#else
+#define H2_STRM_ASSIGN_MAGIC(s,m)  ((void)0)
+#define H2_STRM_ASSERT_MAGIC(s,m)  ((void)0)
+#endif
+
 struct h2_stream {
+#ifdef AP_DEBUG
+    uint32_t magic;
+#endif
     int id;                     /* http2 stream identifier */
     int initiated_on;           /* initiating stream id (PUSH) or 0 */
     apr_pool_t *pool;           /* the memory pool for this stream */


Handle overflow errors in malformed zchunk files

Thanks to Agostino Sarubbo of Gentoo for the heads up!

Signed-off-by: Jonathan Dieter <jdieter@gmail.com>

@@ -115,6 +115,12 @@ static bool comp_add_to_data(zckCtx *zck, zckComp *comp, const char *src,
     ALLOCD_BOOL(zck, comp);
     ALLOCD_BOOL(zck, src);

+    if((comp->data_size > comp->data_size + src_size) ||
+       (src_size > comp->data_size + src_size)) {
+        zck_log(ZCK_LOG_ERROR, "Integer overflow when reading data");
+        return false;
+    }
+
     comp->data = zrealloc(comp->data, comp->data_size + src_size);
     if (!comp->data) {
         zck_log(ZCK_LOG_ERROR, "OOM in %s", __func__);


Check for negative index in dlt_file_message

Fixes #436

Signed-off-by: Michael Methner <mmethner@de.adit-jv.com>

@@ -1718,7 +1718,7 @@ DltReturnValue dlt_file_message(DltFile *file, int index, int verbose)
         return DLT_RETURN_WRONG_PARAMETER;

     /* check if message is in range */
-    if (index >= file->counter) {
+    if (index < 0 || index >= file->counter) {
         dlt_vlog(LOG_WARNING, "Message %d out of range!\r\n", index);
         return DLT_RETURN_WRONG_PARAMETER;
     }


kernel: harden the signature check (#1027)

@@ -1,20 +1,136 @@
+#include "linux/err.h"
 #include "linux/fs.h"
+#include "linux/gfp.h"
+#include "linux/kernel.h"
 #include "linux/moduleparam.h"

 #include "apk_sign.h"
 #include "klog.h" // IWYU pragma: keep
 #include "kernel_compat.h"
+#include "crypto/hash.h"
+#include "linux/slab.h"
+#include "linux/version.h"

-static __always_inline int
-check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
+#include "crypto/sha2.h"
+#else
+#include "crypto/sha.h"
+#endif
+
+struct sdesc {
+	struct shash_desc shash;
+	char ctx[];
+};
+
+static struct sdesc *init_sdesc(struct crypto_shash *alg)
+{
+	struct sdesc *sdesc;
+	int size;
+
+	size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
+	sdesc = kmalloc(size, GFP_KERNEL);
+	if (!sdesc)
+		return ERR_PTR(-ENOMEM);
+	sdesc->shash.tfm = alg;
+	return sdesc;
+}
+
+static int calc_hash(struct crypto_shash *alg, const unsigned char *data,
+		     unsigned int datalen, unsigned char *digest)
+{
+	struct sdesc *sdesc;
+	int ret;
+
+	sdesc = init_sdesc(alg);
+	if (IS_ERR(sdesc)) {
+		pr_info("can't alloc sdesc\n");
+		return PTR_ERR(sdesc);
+	}
+
+	ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
+	kfree(sdesc);
+	return ret;
+}
+
+static int ksu_sha256(const unsigned char *data, unsigned int datalen,
+		unsigned char *digest)
+{
+	struct crypto_shash *alg;
+	char *hash_alg_name = "sha256";
+	int ret;
+
+	alg = crypto_alloc_shash(hash_alg_name, 0, 0);
+	if (IS_ERR(alg)) {
+		pr_info("can't alloc alg %s\n", hash_alg_name);
+		return PTR_ERR(alg);
+	}
+	ret = calc_hash(alg, data, datalen, digest);
+	crypto_free_shash(alg);
+	return ret;
+}
+
+static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset,
+			unsigned expected_size, const char* expected_sha256)
+{
+	ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer-sequence length
+	ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer length
+	ksu_kernel_read_compat(fp, size4, 0x4, pos); // signed data length
+
+	*offset += 0x4 * 3;
+
+	ksu_kernel_read_compat(fp, size4, 0x4, pos); // digests-sequence length
+
+	*pos += *size4;
+	*offset += 0x4 + *size4;
+
+	ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificates length
+	ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificate length
+	*offset += 0x4 * 2;
+
+	if (*size4 == expected_size) {
+		*offset += *size4;
+
+		#define CERT_MAX_LENGTH 1024
+		char cert[CERT_MAX_LENGTH];
+		if (*size4 > CERT_MAX_LENGTH) {
+			pr_info("cert length overlimit\n");
+			return false;
+		}
+		ksu_kernel_read_compat(fp, cert, *size4, pos);
+		unsigned char digest[SHA256_DIGEST_SIZE];
+		if (IS_ERR(ksu_sha256(cert, *size4, digest))) {
+			pr_info("sha256 error\n");
+			return false;
+		}
+
+		char hash_str[SHA256_DIGEST_SIZE * 2 + 1];
+		hash_str[SHA256_DIGEST_SIZE * 2] = '\0';
+
+		bin2hex(hash_str, digest, SHA256_DIGEST_SIZE);
+		pr_info("sha256: %s, expected: %s\n", hash_str, expected_sha256);
+		if (strcmp(expected_sha256, hash_str) == 0) {
+			return true;
+		}
+	}
+	return false;
+}
+
+static __always_inline bool
+check_v2_signature(char *path, unsigned expected_size, const char *expected_sha256)
 {
 	unsigned char buffer[0x11] = { 0 };
 	u32 size4;
 	u64 size8, size_of_block;

 	loff_t pos;
+	bool block_valid;
+
+	const int NOT_EXIST = 0;
+	const int INVALID = 1;
+	const int VALID = 2;
+	int v2_signing_status = NOT_EXIST;
+	int v3_signing_status = NOT_EXIST;

-	int sign = -1;
 	int i;
 	struct file *fp = ksu_filp_open_compat(path, O_RDONLY, 0);
 	if (IS_ERR(fp)) {
@@ -25,7 +141,6 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash)
 	// disable inotify for this file
 	fp->f_mode |= FMODE_NONOTIFY;

-	sign = 1;
 	// https://en.wikipedia.org/wiki/Zip_(file_format)#End_of_central_directory_record_(EOCD)
 	for (i = 0;; ++i) {
 		unsigned short n;
@@ -64,73 +179,38 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash)
 	for (;;) {
 		uint32_t id;
 		uint32_t offset;
-		ksu_kernel_read_compat(fp, &size8, 0x8, &pos); // sequence length
+		ksu_kernel_read_compat(fp, &size8, 0x8,
+				       &pos); // sequence length
 		if (size8 == size_of_block) {
 			break;
 		}
 		ksu_kernel_read_compat(fp, &id, 0x4, &pos); // id
 		offset = 4;
 		pr_info("id: 0x%08x\n", id);
-		if ((id ^ 0xdeadbeefu) == 0xafa439f5u ||
-		    (id ^ 0xdeadbeefu) == 0x2efed62f) {
-			ksu_kernel_read_compat(fp, &size4, 0x4,
-				    &pos); // signer-sequence length
-			ksu_kernel_read_compat(fp, &size4, 0x4, &pos); // signer length
-			ksu_kernel_read_compat(fp, &size4, 0x4,
-				    &pos); // signed data length
-			offset += 0x4 * 3;
-
-			ksu_kernel_read_compat(fp, &size4, 0x4,
-				    &pos); // digests-sequence length
-			pos += size4;
-			offset += 0x4 + size4;
-
-			ksu_kernel_read_compat(fp, &size4, 0x4,
-				    &pos); // certificates length
-			ksu_kernel_read_compat(fp, &size4, 0x4,
-				    &pos); // certificate length
-			offset += 0x4 * 2;
-#if 0
-			int hash = 1;
-			signed char c;
-			for (i = 0; i < size4; ++i) {
-				ksu_kernel_read_compat(fp, &c, 0x1, &pos);
-				hash = 31 * hash + c;
-			}
-			offset += size4;
-			pr_info("    size: 0x%04x, hash: 0x%08x\n", size4, ((unsigned) hash) ^ 0x14131211u);
-#else
-			if (size4 == expected_size) {
-				int hash = 1;
-				signed char c;
-				for (i = 0; i < size4; ++i) {
-					ksu_kernel_read_compat(fp, &c, 0x1, &pos);
-					hash = 31 * hash + c;
-				}
-				offset += size4;
-				if ((((unsigned)hash) ^ 0x14131211u) ==
-				    expected_hash) {
-					sign = 0;
-					break;
-				}
-			}
-			// don't try again.
-			break;
-#endif
+		if (id == 0x7109871au) {
+			block_valid = check_block(fp, &size4, &pos, &offset,
+						  expected_size, expected_sha256);
+			v2_signing_status = block_valid ? VALID : INVALID;
+		} else if (id == 0xf05368c0u) {
+			block_valid = check_block(fp, &size4, &pos, &offset,
+						  expected_size, expected_sha256);
+			v3_signing_status = block_valid ? VALID : INVALID;
 		}
 		pos += (size8 - offset);
 	}

 clean:
 	filp_close(fp, 0);

-	return sign;
+	return (v2_signing_status == NOT_EXIST && v3_signing_status == VALID) ||
+	       (v2_signing_status == VALID && v3_signing_status == NOT_EXIST) ||
+	       (v2_signing_status == VALID && v3_signing_status == VALID);
 }

 #ifdef CONFIG_KSU_DEBUG

 unsigned ksu_expected_size = EXPECTED_SIZE;
-unsigned ksu_expected_hash = EXPECTED_HASH;
+const char *ksu_expected_hash = EXPECTED_HASH;

 #include "manager.h"

@@ -144,9 +224,10 @@ static int set_expected_size(const char *val, const struct kernel_param *kp)

 static int set_expected_hash(const char *val, const struct kernel_param *kp)
 {
-	int rv = param_set_uint(val, kp);
+	pr_info("set_expected_hash: %s\n", val);
+	int rv = param_set_charp(val, kp);
 	ksu_invalidate_manager_uid();
-	pr_info("ksu_expected_hash set to %x\n", ksu_expected_hash);
+	pr_info("ksu_expected_hash set to %s\n", ksu_expected_hash);
 	return rv;
 }

@@ -157,22 +238,23 @@ static struct kernel_param_ops expected_size_ops = {

 static struct kernel_param_ops expected_hash_ops = {
 	.set = set_expected_hash,
-	.get = param_get_uint,
+	.get = param_get_charp,
+	.free = param_free_charp,
 };

 module_param_cb(ksu_expected_size, &expected_size_ops, &ksu_expected_size,
 		S_IRUSR | S_IWUSR);
 module_param_cb(ksu_expected_hash, &expected_hash_ops, &ksu_expected_hash,
 		S_IRUSR | S_IWUSR);

-int is_manager_apk(char *path)
+bool is_manager_apk(char *path)
 {
 	return check_v2_signature(path, ksu_expected_size, ksu_expected_hash);
 }

 #else

-int is_manager_apk(char *path)
+bool is_manager_apk(char *path)
 {
 	return check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH);
 }


Merge pull request from GHSA-xpw8-rcwv-8f8p

Motivation:

It's possible for a remote peer to overload a remote system by issue a huge amount of RST frames. While this is completely valid in terms of the RFC we need to limit the amount to protect against DDOS attacks.

Modifications:

Add protection against RST floods which is enabled by default.

Result:

Protect against DDOS caused by RST floods (CVE-2023-44487)

@@ -14,47 +14,15 @@
  */
 package io.netty.handler.codec.http2;

-import org.hamcrest.CoreMatchers;
-import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+public class Http2EmptyDataFrameConnectionDecoderTest extends AbstractDecoratingHttp2ConnectionDecoderTest {

-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class Http2EmptyDataFrameConnectionDecoderTest {
-
-    @Test
-    public void testDecoration() {
-        Http2ConnectionDecoder delegate = mock(Http2ConnectionDecoder.class);
-        final ArgumentCaptor<Http2FrameListener> listenerArgumentCaptor =
-                ArgumentCaptor.forClass(Http2FrameListener.class);
-        when(delegate.frameListener()).then(new Answer<Http2FrameListener>() {
-            @Override
-            public Http2FrameListener answer(InvocationOnMock invocationOnMock) {
-                return listenerArgumentCaptor.getValue();
-            }
-        });
-        Http2FrameListener listener = mock(Http2FrameListener.class);
-        Http2EmptyDataFrameConnectionDecoder decoder = new Http2EmptyDataFrameConnectionDecoder(delegate, 2);
-        decoder.frameListener(listener);
-        verify(delegate).frameListener(listenerArgumentCaptor.capture());
-
-        assertThat(decoder.frameListener(),
-                CoreMatchers.not(CoreMatchers.instanceOf(Http2EmptyDataFrameListener.class)));
-        assertThat(decoder.frameListener0(), CoreMatchers.instanceOf(Http2EmptyDataFrameListener.class));
+    @Override
+    protected DecoratingHttp2ConnectionDecoder newDecoder(Http2ConnectionDecoder decoder) {
+        return new Http2EmptyDataFrameConnectionDecoder(decoder, 2);
     }

-    @Test
-    public void testDecorationWithNull() {
-        Http2ConnectionDecoder delegate = mock(Http2ConnectionDecoder.class);
-
-        Http2EmptyDataFrameConnectionDecoder decoder = new Http2EmptyDataFrameConnectionDecoder(delegate, 2);
-        decoder.frameListener(null);
-        assertNull(decoder.frameListener());
+    @Override
+    protected Class<? extends Http2FrameListener> delegatingFrameListenerType() {
+        return Http2EmptyDataFrameListener.class;
     }
 }


Merge pull request from GHSA-f76w-fh7c-pc66

* Add group lock to media transport

* Also add group lock to SRTP-DTLS

* Put lock protection to avoid race condition between destroy() & dtls_on_recv()

@@ -298,6 +298,7 @@ PJ_DEF(pj_status_t) pjmedia_transport_udp_attach( pjmedia_endpt *endpt,
     pj_pool_t *pool;
     pj_ioqueue_t *ioqueue;
     pj_ioqueue_callback rtp_cb, rtcp_cb;
+    pj_grp_lock_t *grp_lock;
     pj_status_t status;

@@ -348,18 +349,29 @@ PJ_DEF(pj_status_t) pjmedia_transport_udp_attach( pjmedia_endpt *endpt,
                   pj_sockaddr_get_addr_len(&tp->rtp_addr_name));
     }

+    /* Create group lock */
+    status = pj_grp_lock_create(pool, NULL, &grp_lock);
+    if (status != PJ_SUCCESS)
+        goto on_error;
+
+    pj_grp_lock_add_ref(grp_lock);
+    tp->base.grp_lock = grp_lock;
+
     /* Setup RTP socket with the ioqueue */
     pj_bzero(&rtp_cb, sizeof(rtp_cb));
     rtp_cb.on_read_complete = &on_rx_rtp;
     rtp_cb.on_write_complete = &on_rtp_data_sent;

-    status = pj_ioqueue_register_sock(pool, ioqueue, tp->rtp_sock, tp,
-                                      &rtp_cb, &tp->rtp_key);
+    status = pj_ioqueue_register_sock2(pool, ioqueue, tp->rtp_sock, grp_lock,
+                                       tp, &rtp_cb, &tp->rtp_key);
     if (status != PJ_SUCCESS)
         goto on_error;

     /* Disallow concurrency so that detach() and destroy() are
      * synchronized with the callback.
+     *
+     * Note that we still need this even after group lock is added to
+     * maintain the above behavior.
      */
     status = pj_ioqueue_set_concurrency(tp->rtp_key, PJ_FALSE);
     if (status != PJ_SUCCESS)
@@ -388,8 +400,8 @@ PJ_DEF(pj_status_t) pjmedia_transport_udp_attach( pjmedia_endpt *endpt,
     pj_bzero(&rtcp_cb, sizeof(rtcp_cb));
     rtcp_cb.on_read_complete = &on_rx_rtcp;

-    status = pj_ioqueue_register_sock(pool, ioqueue, tp->rtcp_sock, tp,
-                                      &rtcp_cb, &tp->rtcp_key);
+    status = pj_ioqueue_register_sock2(pool, ioqueue, tp->rtcp_sock, grp_lock,
+                                       tp, &rtcp_cb, &tp->rtcp_key);
     if (status != PJ_SUCCESS)
         goto on_error;

@@ -436,12 +448,13 @@ static pj_status_t transport_destroy(pjmedia_transport *tp)

     /* Must not close while application is using this */
     //PJ_ASSERT_RETURN(!udp->attached, PJ_EINVALIDOP);
-
+
+    /* The following calls to pj_ioqueue_unregister() will block the execution
+     * if callback is still being called because allow_concurrent is false.
+     * So it is safe to release the pool immediately after.
+     */

     if (udp->rtp_key) {
-        /* This will block the execution if callback is still
-         * being called.
-         */
         pj_ioqueue_unregister(udp->rtp_key);
         udp->rtp_key = NULL;
         udp->rtp_sock = PJ_INVALID_SOCKET;
@@ -459,6 +472,8 @@ static pj_status_t transport_destroy(pjmedia_transport *tp)
         udp->rtcp_sock = PJ_INVALID_SOCKET;
     }

+    pj_grp_lock_dec_ref(tp->grp_lock);
+
     PJ_LOG(4,(udp->base.name, "UDP media transport destroyed"));
     pj_pool_release(udp->pool);


Fix memory leak when clients send v5 CONNECT packets.

This occurs when they have a will message that contains invalid property
types.

@@ -103,6 +103,7 @@ int property__process_will(struct mosquitto *context, struct mosquitto_message_a
 				break;

 			default:
+				msg->properties = msg_properties;
 				return MOSQ_ERR_PROTOCOL;
 				break;
 		}


patch 9.0.2111: [security]: overflow in get_number

Problem:  [security]: overflow in get_number
Solution: Return 0 when the count gets too large

[security]: overflow in get_number

When using the z= command, we may overflow the count with values larger
than MAX_INT. So verify that we do not overflow and in case when an
overflow is detected, simply return 0

Signed-off-by: Christian Brabandt <cb@256bit.org>

@@ -975,6 +975,8 @@ get_number(
 	c = safe_vgetc();
 	if (VIM_ISDIGIT(c))
 	{
+	    if (n > INT_MAX / 10)
+		return 0;
 	    n = n * 10 + c - '0';
 	    msg_putchar(c);
 	    ++typed;


patch 9.0.2106: [security]: Use-after-free in win_close()

Problem:  [security]: Use-after-free in win_close()
Solution: Check window is valid, before accessing it

If the current window structure is no longer valid (because a previous
autocommand has already freed this window), fail and return before
attempting to set win->w_closing variable.

Add a test to trigger ASAN in CI

Signed-off-by: Christian Brabandt <cb@256bit.org>

@@ -704,6 +704,8 @@ static char *(features[]) =

 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2106,
 /**/
     2105,
 /**/


Merge pull request #2807 from frankmorgner/piv-logout

Implemented logout for some card drivers

@@ -1050,6 +1050,20 @@ static int asepcos_card_reader_lock_obtained(sc_card_t *card, int was_reset)
 	LOG_FUNC_RETURN(card->ctx, r);
 }

+static int asepcos_logout(sc_card_t *card)
+{
+	int r = SC_ERROR_NOT_SUPPORTED;
+
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
+
+	if (card->type == SC_CARD_TYPE_ASEPCOS_JAVA) {
+		/* in case of a Java card try to select the ASEPCOS applet */
+		r = asepcos_select_asepcos_applet(card);
+	}
+
+	LOG_FUNC_RETURN(card->ctx, r);
+}
+
 static struct sc_card_driver * sc_get_driver(void)
 {
 	if (iso_ops == NULL)
@@ -1066,6 +1080,7 @@ static struct sc_card_driver * sc_get_driver(void)
 	asepcos_ops.list_files        = asepcos_list_files;
 	asepcos_ops.card_ctl          = asepcos_card_ctl;
 	asepcos_ops.pin_cmd           = asepcos_pin_cmd;
+	asepcos_ops.logout            = asepcos_logout;
 	asepcos_ops.card_reader_lock_obtained = asepcos_card_reader_lock_obtained;

 	return &asepcos_drv;


@@ -361,6 +361,11 @@ static int jpki_card_reader_lock_obtained(sc_card_t *card, int was_reset)
 	LOG_FUNC_RETURN(card->ctx, r);
 }

+static int jpki_logout(sc_card_t *card)
+{
+	return jpki_select_ap(card);
+}
+
 static struct sc_card_driver *
 sc_get_driver(void)
 {
@@ -375,6 +380,7 @@ sc_get_driver(void)
 	jpki_ops.set_security_env = jpki_set_security_env;
 	jpki_ops.compute_signature = jpki_compute_signature;
 	jpki_ops.card_reader_lock_obtained = jpki_card_reader_lock_obtained;
+	jpki_ops.logout = jpki_logout;

 	return &jpki_drv;
 }


swtpm_cert: Switch to open() from fopen() for writing certificate

Switch to open from fopen() and make sure we do not follow symlinks.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>

@@ -51,6 +51,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <getopt.h>
+#include <sys/stat.h>

 #include <arpa/inet.h>

@@ -1010,7 +1011,7 @@ main(int argc, char *argv[])
     unsigned long long serial = 1;
     time_t now;
     int err;
-    FILE *cert_file;
+    int cert_file_fd;
     const char *subject = NULL;
     const char *error = NULL;
     int days = 365;
@@ -1695,8 +1696,9 @@ if (_err != GNUTLS_E_SUCCESS) {             \
                             ? GNUTLS_X509_FMT_PEM
                             : GNUTLS_X509_FMT_DER, &out);
     if (cert_filename) {
-        cert_file = fopen(cert_filename, "wb");
-        if (cert_file == NULL) {
+        cert_file_fd = open(cert_filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW,
+                            S_IRUSR|S_IWUSR);
+        if (cert_file_fd < 0) {
             fprintf(stderr, "Could not open %s for writing the certificate: %s\n",
                     cert_filename,
                     strerror(errno));
@@ -1711,22 +1713,22 @@ if (_err != GNUTLS_E_SUCCESS) {             \
                 },
                 .tag = htobe16(TCG_TAG_PCCLIENT_FULL_CERT),
             };
-            if (sizeof(hdr) != fwrite(&hdr, 1, sizeof(hdr), cert_file)) {
+            if (sizeof(hdr) != write(cert_file_fd, &hdr, sizeof(hdr))) {
                 fprintf(stderr, "Could not write certificate header: %s\n",
                         strerror(errno));
-                fclose(cert_file);
+                close(cert_file_fd);
                 unlink(cert_filename);
                 goto cleanup;
             }
         }
-        if (out.size != fwrite(out.data, 1, out.size, cert_file)) {
+        if ((ssize_t)out.size != write(cert_file_fd, out.data, out.size)) {
             fprintf(stderr, "Could not write certificate into file: %s\n",
                     strerror(errno));
-            fclose(cert_file);
+            close(cert_file_fd);
             unlink(cert_filename);
             goto cleanup;
         }
-        fclose(cert_file);
+        close(cert_file_fd);
     } else {
         fprintf(stdout, "%s\n", out.data);
     }


Avoid uint overflow in case the length + index is over UINT_MAX

@@ -363,7 +363,7 @@ ByteVector ByteVector::mid(uint index, uint length) const

   ConstIterator endIt;

-  if(length < 0xffffffff && length + index < size())
+  if(length < size() - index)
     endIt = d->data.begin() + index + length;
   else
     endIt = d->data.end();


Improve the message-splitting algorithm for PRIVMSG and CTCP

This introduces a new message splitting algorithm based on
QTextBoundaryFinder.  It works by first starting with the entire
message to be sent, encoding it, and checking to see if it is over
the maximum message length.  If it is, it uses QTBF to find the
word boundary most immediately preceding the maximum length.  If no
suitable boundary can be found, it falls back to searching for
grapheme boundaries.  It repeats this process until the entire
message has been sent.

Unlike what it replaces, the new splitting code is not recursive
and cannot cause stack overflows.  Additionally, if it is unable
to split a string, it will give up gracefully and not crash the
core or cause a thread to run away.

This patch fixes two bugs.  The first is garbage characters caused
by accidentally splitting the string in the middle of a multibyte
character.  Since the new code splits at a character level instead
of a byte level, this will no longer be an issue.  The second is
the core crash caused by sending an overlength CTCP query ("/me")
containing only multibyte characters.  This bug was caused by the
old CTCP splitter using the byte index from lastParamOverrun() as
a character index for a QString.

@@ -55,6 +55,7 @@ class CoreBasicHandler : public BasicHandler
 signals:
     void displayMsg(Message::Type, BufferInfo::Type, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None);
     void putCmd(const QString &cmd, const QList<QByteArray> &params, const QByteArray &prefix = QByteArray());
+    void putCmd(const QString &cmd, const QList<QList<QByteArray>> &params, const QByteArray &prefix = QByteArray());
     void putRawLine(const QByteArray &msg);

 protected: